Является ли адрес ссылки на разыменованный указатель таким же, как адрес указателя?

В С++ адрес ссылки на разыменованный указатель гарантированно совпадает с адресом указателя?

Или, написанный в коде, есть следующее утверждение, гарантируемое всегда верно?

SomeType *ptr = someAddress;
SomeType &ref = *ptr;
assert(&ref == ptr);

Ответ 1

Да, это правильно и всегда будет правдой.

Ссылка - это не что иное, как псевдоним типа, к которому он обращается. Он не имеет отдельного существования, он всегда связан с тем, с которым он ссылается.

Ответ 2

Да, конечно, если someAddress не является нулевым указателем или иначе не может быть разыменован. В этом случае поведение undefined, хотя ваша реализация может вести себя так, как если бы они были одинаковыми, особенно с низкими уровнями оптимизации.

Если вы хотите быть точным, то &ref на самом деле не является "адресом ссылки", это "адрес ссылки на ссылку". Поскольку ref был привязан к *ptr, это означает, что referand ref и referand (или pointee, если вы предпочитаете) ptr - это один и тот же объект, и, следовательно, два адреса &ref и ptr равны.

И как указывает Бо, вы сравниваете &ref с "значение указателя" или "адрес, хранящийся в указателе", а не "адрес указателя".

Ответ 3

Да, если сама ссылка имеет адрес, она управляется реализацией и не доступна из кода. В любом случае это просто другое имя для одного и того же объекта.

Ответ 4

Да, ваше понимание верное. А для 99. (9)% кода в мире ваш код будет правильным. Для педантов в аудитории (я сам среди них) это утверждение не всегда верно:

SomeType *ptr = someAddress;
SomeType &ref = *ptr;
assert(&ref == ptr);

Рассмотрим эту программу:

#include <cassert>
struct SomeType { void* operator&() { return 0; } };
int main() {
  SomeType *ptr = new SomeType;
  SomeType &ref = *ptr;
  assert(&ref == ptr);
}