Я пытаюсь разобраться в деталях использования указателей и ссылок.
Здесь я оставил несколько комментариев, которые могут показать ход моих мыслей:
using namespace std;
#include <iostream>
int main()
{
int ref; // A variable at an unknown memory address (lets call the address X)
int *point; // An empty memory address (lets call the address Y)
ref = 3; // An int 3 is stored at address X
point = &ref; // Address Y now contains 'ref'
//What happened to address X? Are there two addresses now, known and unknown?
cout << point << endl; //prints address Y
cout << *point << endl; //prints address Y contents (3)
cout << ref << endl; //prints 3 from ?
return 0;
}
У вас может быть 5 разных вещей, указывающих на X (адрес ссылки), и все равно останется только 1 X. Присвоение point = &ref
не меняет X, оно просто дает вам второй способ чтения или записи в тот же X, который вы создали. объявив int ref
.
Меня смущает то, что вы думаете о адресе Y (и я думаю, что вы тоже). Вы сказали: «//Адрес Y теперь содержит «ref». Это неправда, лучше было бы сказать, что переменная-указатель point
теперь содержит адрес X. '// печатает адрес Y', нет, она печатает адрес X. 'cout << *point << endl; // печатает содержимое адреса Y (3)'` нет, печатает содержимое адреса X.
Одной из распространенных причин путаницы является неправильное представление о переменных-указателях. Вера в то, что они особенные и к ним применяются другие правила по сравнению с обычными переменными. Кажется, у вас есть некоторая разновидность этого убеждения, но это неправда, переменные-указатели — это всего лишь обычные переменные. Они могут иметь значения (или не иметь), и им можно присваивать значения; при присвоении они теряют свое предыдущее значение, как и обычные переменные.
@DaveS Скопируйте это — теперь это имеет смысл, спасибо!
Примечание: ничто в этом коде не требует дополнительных вещей, которые делает std::endl
; используйте '\n'
, чтобы завершить строку, если у вас нет веской причины не делать этого.
Чтобы еще больше вас запутать: компилятору разрешено помещать переменные в регистры, чтобы не было использования памяти.
«Что случилось с адресом X?» -- Я не слежу за этим вопросом. Почему что-то должно случиться с X только потому, что вы прямо не упомянули об этом в предыдущей строке? Почему «int 3 хранится по адресу X» не может быть правдой?
An empty memory address (lets call the address Y)
должно читаться A variable at an unknown memory address (lets call the address Y)
, а Address Y now contains 'ref'
должно быть Address Y now contains address X
Линия:
cout << ref << endl;
печатает 3 из памяти, выделенной для переменной ref
, которая в вашей терминологии находится по адресу памяти X
. На самом деле он выделяется в автоматическом хранилище (обычно в стеке) и имеет время жизни переменной ref
, которая является телом функции main
.
Ничего не могло произойти именно «по адресу X», именно значение, которое хранится по «адресу X», было инициализировано (имело какое-то случайное значение) и позже ему было присвоено значение 3. То же самое произошло и с указателем Y, он содержал некоторый начальный случайный адрес, а затем был установлен на X.
Таким образом, по сути, в памяти есть два места, которые обновляются при изменении ref
с этого момента... Скажем ref = 7; //Two memory addresses updated: X (unknown) and Y (known)?
Нет. Обновляется только 1 переменная. point
указывает на то же место 1, где ref
хранит свое значение.
Ааа, кажется, я понимаю... Итак, point = &ref;
получил (ранее неизвестный) адрес памяти ref
? Если это верно, то что было point
до того, как оно указывало на ref
? Просто пустой адрес, который однажды теряется point
, на самом деле указывает?
Значение @CodeN00b point
до присвоения было неопределенным. Могло быть что угодно, и это очень взрывоопасное состояние. В общем, лучше не иметь инициализированную переменную там, где ее может найти ребенок, поэтому избегайте определения переменной до того, как вы узнаете, какое ее значение будет. Например: int *point = &ref;
Понятно, звучит устрашающе :'D Спасибо вам обоим!
Два комментария выше: отсутствие инициализированной переменной должно было означать отсутствие неинициализированной переменной. Извините за это.
@CodeN00b, ты прав; обновил ответ.
Попробуйте следующее:
cout << ref << " " << (void *) (&ref) << endl;
-- выведите адрес переменнойref
.