Неверная форма:
int &z = 12;
Правильная форма:
int y;
int &r = y;
Вопрос:
Почему первый код не так? Что такое значение "ошибки в заголовке?
Неверная форма:
int &z = 12;
Правильная форма:
int y;
int &r = y;
Вопрос:
Почему первый код не так? Что такое значение "ошибки в заголовке?
С++ 03 3.10/1 говорит: "Каждое выражение является либо значением lvalue, либо rvalue". Важно помнить, что lvalueness по сравнению с rvalueness является свойством выражений, а не объектов.
Объекты имен Lvalues, которые сохраняются за пределами одного выражения. Например, obj
, *ptr
, ptr[index]
и ++x
- все lvalues.
Rvalues являются временными, которые испаряются в конце полного выражения, в котором они живут ( "в точку с запятой" ). Например, 1729
, x + y
, std::string("meow")
и x++
- все значения r.
Адрес-оператора требует, чтобы его "операнд должен быть lvalue". если бы мы могли взять адрес одного выражения, выражение будет lvalue, иначе оно будет rvalue.
&obj; // valid
&12; //invalid
int &z = 12;
С правой стороны временный объект типа int
создается из интегрального литерала 12
, но временное не может быть привязано к неконстантной ссылке. Отсюда и ошибка. Это то же самое, что:
int &z = int(12); //still same error
Почему создается временное создание? Поскольку ссылка должна ссылаться на объект в памяти и для существования объекта, он должен быть создан первым. Поскольку объект не указан, это временный объект. У него нет имени. Из этого объяснения стало ясно, почему второй случай в порядке.
Временный объект может быть привязан к константной ссылке, что означает, что вы можете сделать это:
const int &z = 12; //ok
Для полноты я хотел бы добавить, что С++ 11 ввел rvalue-reference, который может привязываться к временному объекту. Поэтому в С++ 11 вы можете написать это:
int && z = 12; //C+11 only
Обратите внимание, что есть &&
intead &
. Также обратите внимание, что const
больше не требуется, даже если объект, к которому привязан z
, является временным объектом, созданным из интегрального литерала 12
.
Так как С++ 11 ввел rvalue-reference, int&
теперь в дальнейшем называется lvalue-reference.
12
- это константа времени компиляции, которая не может быть изменена в отличие от данных, на которые ссылается int&
. Что вы можете сделать, это
const int& z = 12;
Ссылки - это "скрытые указатели" (не равные нулю) для вещей, которые могут меняться (lvalues). Вы не можете определить их константу. Это должно быть "переменным".
ИЗМЕНИТЬ::
Я думаю о
int &x = y;
как почти эквивалентный
int* __px = &y;
#define x (*__px)
где __px
- новое имя, а #define x
работает только внутри блока, содержащего объявление x
.
Это правила языка С++:
12
), является "rvalue" int &ri = 12;
плохо сформированВы должны понимать, что это правила С++. Они просто есть.
Легко придумать другой язык, например С++ ', с несколько разными правилами. В С++ 'было бы разрешено создавать неконстантную ссылку с rvalue. Здесь нет ничего непоследовательного или невозможного.
Но это допустило бы некоторый рискованный код, где программист мог бы не получить то, что он намеревался, и дизайнеры С++ по праву решили избежать этого риска.