Ссылка (reference) — другое имя уже существующего объекта. T& — ссылка на T. Всё, что делается через ссылку, делается с объектом, к которому она привязана.

Зачем нужно

Чтобы функция могла изменить переменную вызывающего кода, ей нужен доступ к самому объекту, а не к копии. Указатель это даёт, но требует явно брать адрес при вызове и разыменовывать внутри. Ссылка даёт тот же доступ без лишнего синтаксиса — и без копирования больших объектов. См. Передача параметров.

Как работает

float value = 1.0f;
float copy = value;
float& reference = value;
 
copy = 7.0f;       // value по-прежнему 1
reference = 9.0f;  // value теперь 9

copy — самостоятельный объект, 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просто имя
в месте вызова&xx

Тонкости

  • Ссылка не создаёт копию объекта и не продлевает ему жизнь. Ссылка на уничтоженный объект — висячая, см. Висячий указатель.
  • Функция может вернуть ссылку — на динамический объект, на статическую или глобальную переменную, на объект, полученный параметром по ссылке, — но не на свою локальную переменную.
  • Возвращённую ссылку можно использовать слева от =: G() = 10; пишет в объект, на который она указывает.
  • Массивы ссылок запрещены, см. Массив.
  • Swap(z, z) для ссылочного Swap с временной переменной безопасен: две ссылки на один объект, значение не меняется.

Частые ошибки

  • Думать, что r = b перепривязывает ссылку.
  • Объявить ссылку без инициализации.
  • Передать литерал в функцию с параметром T&.
  • Привязать int& к const int.
  • Вернуть ссылку на локальную переменную.
  • Считать, что const& гарантирует неизменность объекта.