Ссылки в качестве переменных
В программе (листинг 1.15) приводятся четыре способа адресации и вывода целого значения. Листинг 1.15. REFVAR.CPP (демонстрация ссылочных переменных) 1:#include <iostream.h> 2: Main() 4: { 5: int ivar = 1234; // Переменной присвоено значение 6: int *iptr = &ivar; // Указателю присвоен адрес ivar 7: int &iref = ivar; // Ссылка ассоциирована с ivar 8: int *p = &iref; // Указателю присвоен адрес iref 9: 10: cout « "ivar == " « ivar « '\n'; 11: cout « "*iptr == " « *iptr « '\n'; 12: cout « "iref == " « iref « '\n'; 13: cout « "*p == " << *p « '\n'; 14: return 0; 15:}
В строках 5-8 объявляются четыре переменные. Первая — простое целое ivar, инициализированное значением 1234. Следующая, — указатель на целое с именем iptr, которой присвоен адрес ivar. Третья объявлена как ссылочная переменная. Строка int &iref = ivar; объявляет iref как ссылку на целое значение. Что касается iref, то ей присваивается ivar не как значение переменной, а как адрес в памяти. Следуя объявлению, iref указывает на ivar подобно указателю. Как показано в строке 12, оператор cout « "iref == " « iref « '\n'; выводит значение ivar — 1234. Это происходит благодаря использованию iref в качестве ссылки на местоположение переменной ivar в памяти. Четвертое объявление в строке 8 создает еще один указатель — p, которому присваивается адрес, хранящийся в iref. Строки 6 и 8 дают одинаковый результат. В обеих строках создаются указатели, ссылающиеся на ivar. Как показано в строке 13, употребление указателя в выражении *p дает доступ к значению ivar. На рис. 1.2 проиллюстрирована взаимосвязь переменных из листинга 1.15. Как видно из иллюстрации, использование iref очень похоже на использование разыменования указателя *p. В обоих выражениях осуществляется доступ к значению ivar — 1234. Рис. 1.2. Взаимосвязь переменных в листинге 1.15, REFVALCPP При использовании ссылок следует помнить одно правило: однажды инициализировав ссылку, ей нельзя присвоить другое значение.
В REFVAL.CPP вы не можете объявить новую целочисленную переменную и присвоить ее адрес iref: int anotherInt; iref = anotherInt; // ??? Это присваивание не заставит iref ссылаться на anotherInt. Это выражение присвоит значение anotherInt объекту, на который iref ссылается, другими словами — ivar. Так же вы можете присваивать новые значения объекту, к которому относится ссылка. Например, выражение iref = 4321; присвоит ivar значение 4321. Эти правила будет легче запомнить, если представить себе ссылки как неизменяемые альтернативные имена, похожие на указатели (но не идентичные им!). Как следует из вышесказанного, ссылки должны быть инициализированы при их объявлении. Строка 7, к примеру, не может быть написана как int &iref; // ???
В отличие от указателей, которые могут быть объявлены в неинициализированном состоянии или установлены в нуль (если указатель не ссылается на необходимые данные), ссылки всегда ссылаются на объект. Для ссылок не существует аналога нулевого указателя. Ссылки нельзя инициализировать значениями в следующих четырех особых случаях: при их объявлении с ключевым словом ехtеrn, при использовании в качестве параметров функции, при использовании в качестве типа возвращаемого значения функции или в объявлениях классов.
Не существует операторов, непосредственно производящих действия над ссылками. Все операции совершаются только над соответствующими объектами.
Добавьте между строками 13 и 14 листинга 12.15 следующий оператор: iref++; Компилятор сгенерирует код, инкрементирующий ivar — переменную, на которую ссылается iref. Оператор не совершит никаких действий непосредственно над iref.
Ссылки также могут ссылаться на константы.
Разумеется, вы не можете присвоить значение непосредственно ссылке. Объявление int &iref = 1234; // ??? вызовет сообщение об ошибке при компиляции, поскольку 1234 не является объектом, на который iref сможет сослаться. Вы можете, конечно, объявить константную ссылку на допустимый объект следующим образом: int x = 1234; // Объявление и инициализация целочисленного объекта const int &iref = x; // Объявление iref как константной ссылки на x Этот прием очень полезен, поскольку эффективно превращает переменную в константу, которую нельзя подвергнуть изменениям. Например, вы можете записать значение x в выходной поток с помощью ссылки следующим образом: cout << "iref = " << iref << '\n'; // Все в порядке Вы также можете изменить значение переменной x: x = 4321; // Тоже годится Поскольку iref — константа, то вы, конечно, не сможете присвоить новое значение x через ссылку: iref = 4321; // ??? Нельзя Попытка скомпилировать последнее выражение приведет к выдаче сообщения об ошибке "Cannot modify a const object in function main()" (Нельзя изменить константный объект в функции main()). ©2015 arhivinfo.ru Все права принадлежат авторам размещенных материалов.
|