Подтвердить что ты не робот

Error: неверная инициализация неконстантной ссылки типа 'int & из rvalue типа' int

Неверная форма:

int &z = 12;

Правильная форма:

int y;
int &r = y;

Вопрос:
Почему первый код не так? Что такое значение "ошибки в заголовке?

4b9b3361

Ответ 1

С++ 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

Ответ 2

int &z = 12;

С правой стороны временный объект типа int создается из интегрального литерала 12, но временное не может быть привязано к неконстантной ссылке. Отсюда и ошибка. Это то же самое, что:

int &z = int(12); //still same error

Почему создается временное создание? Поскольку ссылка должна ссылаться на объект в памяти и для существования объекта, он должен быть создан первым. Поскольку объект не указан, это временный объект. У него нет имени. Из этого объяснения стало ясно, почему второй случай в порядке.

Временный объект может быть привязан к константной ссылке, что означает, что вы можете сделать это:

const int &z = 12; //ok

С++ 11 и Rvalue Reference:

Для полноты я хотел бы добавить, что С++ 11 ввел rvalue-reference, который может привязываться к временному объекту. Поэтому в С++ 11 вы можете написать это:

int && z = 12; //C+11 only 

Обратите внимание, что есть && intead &. Также обратите внимание, что const больше не требуется, даже если объект, к которому привязан z, является временным объектом, созданным из интегрального литерала 12.

Так как С++ 11 ввел rvalue-reference, int& теперь в дальнейшем называется lvalue-reference.

Ответ 3

12 - это константа времени компиляции, которая не может быть изменена в отличие от данных, на которые ссылается int&. Что вы можете сделать, это

const int& z = 12;

Ответ 4

Ссылки - это "скрытые указатели" (не равные нулю) для вещей, которые могут меняться (lvalues). Вы не можете определить их константу. Это должно быть "переменным".

ИЗМЕНИТЬ::

Я думаю о

int &x = y;

как почти эквивалентный

int* __px = &y;
#define x (*__px)

где __px - новое имя, а #define x работает только внутри блока, содержащего объявление x.

Ответ 5

Связывание с константой и константой ссылается на разные правила

Это правила языка С++:

  • выражение, состоящее из литерального числа (12), является "rvalue"
  • не разрешено создавать неконстантную ссылку с rvalue: int &ri = 12; плохо сформирован
  • разрешено создавать константную ссылку с rvalue: в этом случае компилятор создает неназванный объект; этот объект будет сохраняться до тех пор, пока существует сама ссылка.

Вы должны понимать, что это правила С++. Они просто есть.

Легко придумать другой язык, например С++ ', с несколько разными правилами. В С++ 'было бы разрешено создавать неконстантную ссылку с rvalue. Здесь нет ничего непоследовательного или невозможного.

Но это допустило бы некоторый рискованный код, где программист мог бы не получить то, что он намеревался, и дизайнеры С++ по праву решили избежать этого риска.