← Назад к вопросам

Можно ли ссылке присвоить другой адрес памяти?

2.0 Middle🔥 281 комментариев
#Язык C++

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Нет, ссылке нельзя присвоить другой адрес памяти после инициализации. Это одно из ключевых различий между ссылками и указателями в C++.

Ссылка связана с объектом навсегда

Когда вы инициализируете ссылку, она привязывается к конкретному объекту. После инициализации эта связь неразрывна:

int a = 10;
int b = 20;

int& ref = a;        // ссылка привязана к переменной a
// ref теперь всегда указывает на a

ref = b;             // ЭТО НЕ переприсваивает ссылку!
                     // Это присваивает значение b переменной a
                     // a становится равна 20, ref всё ещё указывает на a

cout << a << endl;   // выведет 20
cout << ref << endl; // выведет 20 (потому что это а)

Почему нельзя переприсвоить

Это архитектурное решение языка C++:

  • Ссылка - это псевдоним, а не контейнер адреса
  • Компилятор не выделяет память для хранения адреса
  • Ссылка - это просто новое имя для существующего объекта
  • Нет способа изменить, на какой объект ссылается ссылка
// На уровне компилятора:
int a = 10;
int& ref = a;
// ref - это просто другое имя для a, встроенное в код
// При обращении к ref компилятор генерирует код доступа к a

Это отличается от указателей

Указатели можно переприсваивать, потому что они хранят адрес:

int a = 10;
int b = 20;

int* ptr = &a;       // указатель содержит адрес a
ptr = &b;            // ✓ Можно переприсвоить адрес b
cout << *ptr << endl; // 20

// Но со ссылками:
int& ref = a;
ref = b;             // ✗ Нельзя - присваивает значение, не адрес

Практическое применение

Ссылки используются когда нужна гарантия, что объект не изменится:

// Гарантирует, что func работает с параметром until конца
void processArray(std::vector<int>& arr) {
    // arr всегда указывает на переданный вектор
    for (int& val : arr) {
        val *= 2;
    }
}

std::vector<int> myArray = {1, 2, 3};
processArray(myArray);  // myArray в функции - это ссылка на исходный вектор

Когда нужна гибкость - используем указатели

Если нужна возможность изменять адрес, используйте указатели:

int a = 10;
int b = 20;

int* ptr = &a;       // указатель на a
ptr = &b;            // переприсваиваем на b
ptr = nullptr;       // можно и на nullptr

// Или используем ссылку через указатель:
int* ptrA = &a;
int& ref = *ptrA;    // ссылка на объект, на который указывает ptr
ptrA = &b;
// ref всё ещё указывает на a, хотя ptrA теперь указывает на b

Исключение: null ссылка (плохая практика)

Технически, можно заставить ссылку быть undefined через undefined behavior:

int* ptrNull = nullptr;
int& ref = *ptrNull;  // ✓ Компилируется, но это undefined behavior!
// ref теперь "указывает" на nullptr - это крайне опасно

Но это не является проектным решением, а результатом ошибки.

Вывод

Ссылка после инициализации связана с объектом навсегда. Это её главное свойство и преимущество перед указателями - гарантирует корректность доступа. Если вам нужна переприсвояемая ссылка на объект, используйте указатель.

Можно ли ссылке присвоить другой адрес памяти? | PrepBro