Инициализация ссылки в C++

Может ли кто-нибудь объяснить мне, почему существует разница между этими двумя утверждениями?

class A{};

const A& a = A();         // correct 

A& b = A();               // wrong

Он говорит о недопустимой инициализации неконстантной ссылки типа A& из временной ссылки типа A.

Почему const имеет значение здесь?


person skydoor    schedule 23.02.2010    source источник


Ответы (5)


Неконстантные ссылки должны быть инициализированы l-значениями. Если бы вы могли инициализировать их временными объектами, что бы сделало следующее?

int& foo = 5;
foo = 6; // ?!

Ссылки const обладают особым свойством продлевать срок службы рефери, и, поскольку они const, нет никакой возможности, что вы попытаетесь изменить что-то, что не хранится в памяти. Например:

const int& foo = 5;
foo = 6; // not allowed, because foo is const.

Помните, что ссылки на самом деле должны ссылаться на что-то, а не только на временные переменные. Например, справедливо следующее:

int foo = 5;
int& bar = foo;
bar = 6;
assert(foo == 6);
person Peter Alexander    schedule 23.02.2010
comment
Подождите, значит ли это, что я могу использовать const classA& ref = ReturnsClassAByValue();? Я думал, что темп умрет на следующей строке. - person Lucas; 23.02.2010
comment
Да, вы могли бы использовать это. Временная переменная будет существовать столько же, сколько и ссылочная переменная: herbsutter.spaces .live.com/blog/cns!2D4327CC297151BB!378.entry - person Josh Townzen; 23.02.2010
comment
Да, константные ссылки продлевают срок службы временного объекта до срока службы ссылок. Во многих отношениях вы можете думать о const T& как о const T — просто без дорогостоящего копирования;) - person Peter Alexander; 23.02.2010

Терминология здесь немного сбивает с толку; вы можете исследовать их немного дальше. Вот краткий ответ:

Вы назначаете временный объект (результат вызова конструктора класса) переменной. Временный объект — это R-ценность. Вы не можете присвоить значение R неконстантной ссылке.

Вам разрешено присваивать R-значение константной ссылке, хотя причина этого довольно неясна.

person jwismar    schedule 23.02.2010

В языке C++ недопустимо присоединять неконстантную ссылку к rvalue, в то время как присоединение константной ссылки к rvalue совершенно нормально. Например, это законно

const int& r = 5;

пока это не

int &r = 5; // ERROR

Временный объект типа A, возвращаемый выражением A(), является значением r, поэтому приведенное выше правило применимо и в вашем случае.

person AnT    schedule 23.02.2010
comment
Значение r — это безымянное временное значение, подобное возвращаемому значением функции. - person thebretness; 23.02.2010
comment
@thebretness: Не обязательно. Например, константа перечисления является значением r, хотя оно имено. - person AnT; 23.02.2010

Для временного/rvalue у вас может быть только константная ссылка.

У вас может быть неконстантная ссылка на невременное/lvalue.

A a;
A& b = a;

Я считаю, что причина этого заключается в том, чтобы подчеркнуть тот факт, что rvalue является временным, поскольку возможность изменить что-то, что скоро исчезнет, ​​не имеет большого значения.

person R Samuel Klatchko    schedule 23.02.2010
comment
Предоставленный; Я думаю, что ОП ищет, почему это так. - person fbrereto; 23.02.2010

Потому что стандарт говорит так:

§8.5.3.5 ... В противном случае ссылка должна быть ссылкой lvalue на неизменяемый константный тип ...

Однако, если очень захотеть, то можно получить:

#include <iostream>
int main()
{
  const int & cr=5;
  int & r=const_cast<int &>(cr);
  r=6;
  std::cout<<r;
}
// outputs 6 with c++/clang++, Debian 8, amd64

Но имейте в виду, что предполагаемая константа cr также больше не является константой, и вы подвергаетесь неопределенному поведению. (§1.9 (4))

Как следует из приведенного выше кода, для разницы нет технической причины. Скорее, дизайнерам снились кошмары о том, что пользователи будут делать с неконстантными ссылками на временные объекты.

person Heiko Bloch    schedule 03.10.2016