Правильно ли я сказал, что const_cast с последующей модификацией ref-to-const, привязанного к временному, - это нормально? - PullRequest
19 голосов
/ 23 ноября 2011

Я хотел бы проверить свое понимание и выводы по этому вопросу.


На IRC спросили:

Приемлемо ли const_cast a const ссылка, привязанная к временному объекту?

Перевод: он имеет привязку ref-to-const к временному, и он хочет отбросить его const- необходимость его изменить.

Мой ответ состоял в том, что я задал аналогичный вопрос ранее, когда казалось, что консенсус заключается в том, что сами временники не являются по своей природе const, и, таким образом, чтовы можете отбросить const -ность ссылки, которая у вас есть, и изменить их в результате.И до тех пор, пока этот исходный ref-to-const все еще существует, это не повлияет на время жизни временного пользователя.

То есть:

int main()
{
   const int& x = int(3);

   int& y = const_cast<int&>(x);
   y = 4;

   cout << x;
}
// Output: 4
// ^ Legal and safe

Я прав?


(Конечно, действительно ли такой код рекомендуется или нет, это совсем другое дело!)

Ответы [ 2 ]

9 голосов
/ 23 ноября 2011

Нет.

Во-первых, насколько я могу судить, является ли это буквальным или нет, не имеет значения.R-значения типов, не относящихся к классу, всегда имеют типы, не относящиеся к cv (§3.10 / 9), однако в §8.5.3 (инициализация ссылки) мы имеем:

Ссылка на тип«Cv1 T1» инициализируется выражением типа «cv2 T2» следующим образом:

[...]

-

В противном случае, временный тип «cv1 T1 ”создается и инициализируется из выражения инициализатора с использованием правил инициализации нереферентной копии (8.5).Ссылка затем привязывается к временному.Если T1 связан со ссылкой на T2, cv1 должен иметь ту же квалификацию cv или большую квалификацию, чем cv2;в противном случае программа некорректна.

(Все предыдущие пункты касаются либо lvalue, либо типов классов.)

В нашем случае имеем:

int const& x = ...;

То есть cv1 T1 равно int const, а созданный нами временный объект имеет тип int const.Это const верхнего уровня (для объекта), поэтому любая попытка изменить его - неопределенное поведение.

По крайней мере, это моя интерпретация.Хотелось бы, чтобы стандарт был немного яснее об этом.

1 голос
/ 23 ноября 2011

Ответ зависит от того, как создается временный объект и как инициализируется ссылка.

Если вы сами явно создали временный объект как объект неконстантного типа, и ситуация гарантирует, что const-ссылка привязана именно к созданному вами временному объекту, тогда вы можете безопасно отбросить константу ссылки и изменить объект.

С другой стороны, если временное было неявно создано для вас компилятором, то само временное будет const. В этом случае изменение этого временного ведет к UB.

К сожалению, сам по себе стандарт языка C ++, похоже, не гарантирует каких-либо ситуаций, в которых обязательно используется первый подход инициализации. В любом контексте компилятору разрешено вводить дополнительную временную копию вашего исходного временного. Новое временное будет постоянным (как указано выше) и, следовательно, неизменяемым. Происходит это или нет, определяется реализацией, как указано в 8.5.3 / 5.

Таким образом, в общем случае ответ отрицательный, в то время как ответ для конкретной реализации может отличаться.

...