Ссылочная инициализация в C++

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

class A{};

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

A& b = A();               // wrong

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

Почему const важно здесь?

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);

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

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

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

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

const int& r = 5;

пока это не

int &r = 5; // ERROR

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

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

Вы можете иметь неконстантную ссылку на не временную /lvalue.

A a;
A& b = a;

Я полагаю, что причина состоит в том, чтобы усилить тот факт, что значение является временным, поскольку нет никакой ценности в возможности изменить то, что собирается на мгновение исчезнуть.

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

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

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

#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))

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

Другие вопросы по тегам