Ссылка является псевдонимом, синонимом, или альтернативным именем переменной. Ссылка не занимает дополнительного пространства в памяти и является просто другим именем величины, на которую она ссылается. Формат объявления ссылки: тип& имя; , где тип – это тип величины, на которую указывает ссылка, & - оператор ссылки, означающий, что следующее за ним имя является именем переменной ссылочного типа, например:
int kol;
int& pal = kol; // ссылка pal – альтернативное имя для kol
Существуют следующие правила использования ссылок: 1) переменная-ссылка должна явно инициализироваться при её описании, кроме случаев, когда она является параметром функции или ссылается на поле данных класса; 2) после инициализации, ссылке не может быть присвоена другая переменная; 3) тип ссылки должен совпадать с типом величины, на которую она ссылается; 4) не разрешается определять указатели на ссылки, создавать массивы ссылок и ссылки на ссылки.
Одним из наиболее важных применений ссылок является передача аргументов в функции. Когда осуществляется передача по значению, вызываемая функция создаёт новые переменные, имеющие те же типы, что и передаваемые аргументы, и копирует значения аргументов в эти переменные. При этом функция не имеет доступа к переменным-аргументам, а работает со сделанными ей копиями значений. Передача аргументов по ссылке происходит по другому механизму. Вместо того, чтобы передавать функции значение переменной, ей передаётся ссылка на эту переменную (фактически в функцию передаётся адрес переменной-аргумента в памяти). Важной особенностью передачи аргументов по ссылке является то, что функция имеет прямой доступ к значениям аргументов. К достоинствам ссылочного механизма также относится возможность возвращения функцией не одного, а множества значений.
Рассмотрим следующий пример, демонстрирующий применение ссылочного механизма передачи аргументов.
#include …
void func(float, float&, float&); // прототип
int main() {
float number, intpart, drobpart;
cout << "\nVvedite veschestv. chislo: ";
cin >> number; // ввод числа пользователем
func(number, intpart, drobpart); // нахождение целой и дробной части (& отсутствуют)
cout << "Celaja chast ravna " << intpart // вывод результатов
<< ", drobnaja chast ravna " << drobpart << endl;
getch(); return 0;
}
//----------функция вычисляет целую и дробную часть вещ. числа
void func(float n, float& intp, float& drobp) {
int temp = static_cast<int>(n); // преобразование к типу int,
intp = static_cast<float>(temp); // и обратно во float
drobp = n - intp; // вычитаем целую часть
}
Программа выделяет целую и дробную часть введённого числа. Результат работы программы:
Vvedite veschestv. chislo: 55.25
Celaja chast ravna 55, drobnaja chast ravna 0.25
Обратите внимание на то, что при вызове функции отсутствуют &.
Необходимо разобраться, каким образом функция func() возвращает найденные значения в главную функцию. Дело в том, что при использовании ссылочного механизма функция ничего "не возвращает", она дистанционно управляет переменными intpart и drobpart. Имена intp и intpart связаны с одной и той же областью памяти, так же как и пара имён drobp и drobpart. Другими словами, используя имя intp в функции func(), фактически мы оперируем значением переменной intpart функции main().
Таким образом, ссылочный механизм напоминает устройство дистанционного управления: вызывающая программа указывает функции переменные, которые нужно обработать, а функция обрабатывает эти переменные, даже не зная их настоящих имён. Использование ссылок вместо передачи по значению более эффективно, поскольку не требует копирования параметров, что имеет значение при передаче структур данных большого объёма.
Итак, мы рассмотрели два способа передачи аргументов в функцию: по значению и по ссылке. Третьим способом передачи аргументов в функцию является использование указателей. Этот способ мы рассмотрим позднее.