Ссылка (reference) — другое имя уже существующего объекта. T& —
ссылка на T. Всё, что делается через ссылку, делается с объектом, к которому
она привязана.
Зачем нужно
Чтобы функция могла изменить переменную вызывающего кода, ей нужен доступ к самому объекту, а не к копии. Указатель это даёт, но требует явно брать адрес при вызове и разыменовывать внутри. Ссылка даёт тот же доступ без лишнего синтаксиса — и без копирования больших объектов. См. Передача параметров.
Как работает
float value = 1.0f;
float copy = value;
float& reference = value;
copy = 7.0f; // value по-прежнему 1
reference = 9.0f; // value теперь 9copy — самостоятельный объект, reference — доступ к value.
& в объявлении — часть типа. & в выражении (&value) — взятие адреса.
Ссылку инициализируют самим объектом, а не его адресом.
Привязка — один раз и навсегда
Ссылку обязательно инициализировать: float& bad; — CE. Состояния «ни с
чем не связана», как у nullptr, нет.
После инициализации ссылку нельзя перепривязать. Присваивание пишет в объект, а не меняет привязку:
float z = 1.0f;
float v = 2.0f;
float& reference = z;
reference = v; // z = 2, reference всё ещё про z
reference = 8.0f; // z = 8, v = 2Константная ссылка
const T& даёт доступ к объекту только для чтения:
float z = 1.0f;
const float& rf = z;
// rf = 7.0f; // CE
z += 1.0f; // rf видит 2Константная ссылка не замораживает объект — она запрещает менять его только через себя.
Ограничить доступ можно, расширить — нет:
const int value = 10;
const int& good = value; // OK
int& bad = value; // CE: отбросила бы constСсылки и временные объекты
int& привязывается только к изменяемому объекту (lvalue), const int& —
ещё и к временному объекту, например к литералу (prvalue, см.
Категории значения):
void PrintX(const int& x);
PrintX(10); // OK: временный объект 10 живёт до конца выражения вызова
void Swap(float& lhs, float& rhs);
Swap(1.0f, 2.0f); // CE: cannot bind non-const lvalue reference to an rvalueСсылка или указатель
| Указатель | Ссылка | |
|---|---|---|
| может быть «пустым» | nullptr | нет |
| можно перенаправить | да (если не T* const) | нет |
| синтаксис доступа | *p | просто имя |
| в месте вызова | &x | x |
Тонкости
- Ссылка не создаёт копию объекта и не продлевает ему жизнь. Ссылка на уничтоженный объект — висячая, см. Висячий указатель.
- Функция может вернуть ссылку — на динамический объект, на статическую или глобальную переменную, на объект, полученный параметром по ссылке, — но не на свою локальную переменную.
- Возвращённую ссылку можно использовать слева от
=:G() = 10;пишет в объект, на который она указывает. - Массивы ссылок запрещены, см. Массив.
Swap(z, z)для ссылочногоSwapс временной переменной безопасен: две ссылки на один объект, значение не меняется.
Частые ошибки
- Думать, что
r = bперепривязывает ссылку. - Объявить ссылку без инициализации.
- Передать литерал в функцию с параметром
T&. - Привязать
int&кconst int. - Вернуть ссылку на локальную переменную.
- Считать, что
const&гарантирует неизменность объекта.