CodeInside
@CodeInside

Что представляет собой ссылка?

Как бы грамотно сформулировать ответ? Ибо сказать, что она представляет собой другое имя переменной мало и как-то неграмотно.
  • Вопрос задан
  • 755 просмотров
Решения вопроса 1
Nipheris
@Nipheris Куратор тега C++
Ну конечно что ждет от вас препод, нам тут все равно не угадать. Я бы как раз и ответил, что это имя для переменной. Я не соглашусь с некоторыми ответами здесь, т.к. не всегда для ссылки компилятор будет выделять память - локальная ссылка на локальную же переменную как раз таки будет просто вторым именем в таблице идентификаторов компилятора при компиляции программы.

Главная фишка ссылки в том, что это абстрактное l-value, т.е. сущность, в которую можно что-то присвоить (если базовый тип - не константный). То есть ссылка всегда оборачивает какой-либо адрес в памяти, причем на время жизни ссылки этот адрес постоянен (ссылку нельзя "переставить" на другую область памяти). Именно поэтому ссылки всегда нужно инициализировать.
ЧЕМ инициализировать - другое дело. Можно переменной, а можно - разыменованным указателем.

В зависимости от ситуации технически ссылка может быть реализована по-разному. Если это ссылка на лок. переменную, то большинство компиляторов просто добавят себе новое имя в таблицу. Никакой дополнительной памяти выделяться не будет. Если же ссылка приходит как параметр или отдается как возвращаемое значение - то тут скорее всего понадобится реализовать ее как указатель (указатель передавать/возвращать). Однако, еще раз напомню: ссылка скрывает технические подробности, вы с ней работаете как с обычной переменной. Более того, она скрывает настолько, что даже может продлевать жизнь временным объектам.

Теперь попробуем сранить ссылку и другие сущности в языке.
Определение ссылки vs определение обычной переменной:
определение обычной переменной это всегда выделение памяти и добавление нового имени в таблицу компилятора для этой области памяти. Определение ссылки - это прежде всего ОПРЕДЕЛЕНИЕ ИМЕНИ, а уже в тех случаях, когда привязку этого ИМЕНИ к АДРЕСУ невозможно осуществить во время компиляции (т.е. например в случае передачи ссылки как параметра функции), то для реализации ссылки применятся указатель. Важно, что компилятор сам выбирает способ реализации поведения ссылки. В любом случае, назначение ссылки - обернуть в l-value уже ВЫДЕЛЕННУЮ память (совершенно не важно, на стеке, куче или где-то еще). Новой памяти для хранения значения целевого типа НЕ выделяется. Если у вас есть переменная и ссылка/несколько ссылок на нее, то при присвоении значения через любую из сущностей вы будете менять одну и ту же область памяти.

Ссылка vs указатель:
- самое важное отличие - указатель САМ ПО СЕБЕ является переменной. Под указатель int* компилятор выделит память также, как и под int. Указатель существует сам по себе, ему (если он не const) можно присваивать новые значение, можно присвоить nullptr. Можно даже хранить в нем совершенно некорректный адрес и все будет ок до тех пор, пока вы не разыменуете его. Только когда вы разыменовываете указатель, вы превращаете его в l-value, и с этого момента между ним и ссылкой разницы нет.
- второе отличие - собственно необходимость разыменования. Т.к. указатель - самостоятельная переменная, для обращения по адресу, на который указатель смотрит, нужно сделать ему *p. Именно в этот момент компилятор начинает рассматривать значение указателя как адрес в памяти, с которым вы собираетесь что-то сделать (если быть совсем точным, но не в момент разыменования, а при попытке чтения/записи. В принципе вы можете даже инициализировать ссылку некорректным указателем, и программа не упадет, пока вы не попытаетесь читать/присваивать по этой ссылке).
- с учетом сказанного, ссылку можно грубо считать "константым указателем с автоматическим разыменованием". Грубо, т.к. согласно стандарту есть нюансы, такие как вышеупомянутое продлевание жизни временным объектам.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 3
@dmitryKovalskiy
программист средней руки
Это переменная, хранящая внутри себя адрес памяти, в котором хранится объект некого типа. В отличие от указателя - ссылка должна быть проинициализирована начальным значением и не может быть null.
Ответ написан
gbg
@gbg Куратор тега C++
Любые ответы на любые вопросы
Более жесткий вариант указателя. Ссылаться можно только на существующую переменную, например.
Ну и чтобы получить значение по ссылке, нет необходимости в явном разименовывании.

Подробности, например, в вики (в качестве старта)
Ответ написан
Комментировать
slinkinone
@slinkinone
Агент "Везде успеть"
Допустим имеем такой код:
int a = 5; // это переменная а = 5 (допустим по адресу 0x333333)
// она хранится в памяти в какой-то ячейке и у этой ячеки есть свой номер
// и чтобы узнать этот номер надо к переменной "а" применить "&" - это адрес или ссылка
// а указатель специальный тип для хранения адреса переменной и объявляется так
int* ptrA = &a;
// указатель должен быть сразу проинициализирован
// теперь ptrA = 0x333333
// *ptrA = 5; - мы разименовали адрес хранящийся в переменной ptrA... Сказали процессору получить знвчение по адресу что в ptrA
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы