ошибка: неверная инициализация неконстантной ссылки типа «int &» из значения типа «int» - PullRequest
76 голосов
/ 28 ноября 2011

Неправильная форма:

int &z = 12;

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

int y;
int &r = y;

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

Ответы [ 5 ]

118 голосов
/ 28 ноября 2011

C ++ 03 3.10 / 1 гласит: «Каждое выражение является либо lvalue, либо rvalue». Важно помнить, что lvalueness vs. rvalueness - это свойство выражений, а не объектов.

L Значения имен объектов, которые сохраняются за пределами одного выражения. Например, obj, *ptr, ptr[index] и ++x - все lvalues.

R-значения - это временные значения, которые испаряются в конце полного выражения, в котором они живут («в точке с запятой»). Например, 1729, x + y, std::string("meow") и x++ - все значения r.

Оператор адреса требует, чтобы его «операнд был lvalue». если бы мы могли взять адрес одного выражения, выражение является lvalue, иначе это rvalue.

 &obj; //  valid
 &12;  //invalid
45 голосов
/ 28 ноября 2011
int &z = 12;

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

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

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

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

const int &z = 12; //ok

C ++ 11 и Rvalue Ссылка:

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

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

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

Поскольку в C ++ 11 введено rvalue-reference , int& отныне называется lvalue-reference .

8 голосов
/ 28 ноября 2011

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

const int& z = 12;
4 голосов
/ 29 ноября 2011

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

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

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

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

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

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

0 голосов
/ 28 ноября 2011

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

РЕДАКТИРОВАТЬ ::

Я думаю о

int &x = y;

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...