Справочная инициализация в C ++
-
22-09-2019 - |
Вопрос
Кто -нибудь может объяснить мне, почему есть разница между этими двумя утверждениями?
class A{};
const A& a = A(); // correct
A& b = A(); // wrong
В нем говорится, что неверная инициализация неконтролируемой ссылки типа A&
от временного типа A
Почему const
Здесь важно?
Решение
Неконтролируемые ссылки должны быть инициализированы с помощью 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);
Другие советы
Терминология этого немного запутанна; Вы можете исследовать их немного дальше. Вот короткий ответ, хотя:
Вы назначаете временный объект (результат вызова конструктора класса) переменной. Временный объект-это R-значение. Вы не можете присвоить r-значение неконфессиональному ссылке.
Вам разрешено присвоить значение r на справочник CONST, хотя обоснование для того, чтобы оно было довольно неясным.
На языке C ++ незаконно прикреплять неконфикцию к RVALUE, в то время как вполне нормально прикрепить константу к RVALUE. Например, это законно
const int& r = 5;
Пока это не
int &r = 5; // ERROR
Временный объект типа A
возвращен выражением A()
это RVALUE, поэтому приведенное выше правило также применяется в вашем случае.
Для временного/RVALUE вы можете иметь только константу.
У вас может быть неконтролируемая ссылка на невременную/LVALUE.
A a;
A& b = a;
Я считаю, что причина, по которой состоит в том, чтобы укрепить тот факт, что RVALUE является временным, так как существует небольшая ценность в возможности изменить то, что на мгновение исчезнет.
Потому что стандарт так говорит:
§8.5.3.5 ... В противном случае ссылка должна быть ссылкой на нелетую константную тип ...
Однако, если вы хотите этого, вы можете получить:
#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))
Как предложено приведенным выше кодом, нет технической причины разницы. Скорее, у дизайнеров были кошмары о том, что пользователи будут делать с неконфессиональными ссылками на временные.