Подтвердить что ты не робот

Правильно ли я говорю, что const_cast, за которым следует модификация на ref-to-const, связанная с временным, в порядке?

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


В IRC было задано вопрос:

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

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

Мой ответ состоял в том, что я ранее задавал аналогичный вопрос, где, как представляется, консенсус заключался в том, что сами временные рамки не являются по своей сути 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

Я прав?


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

4b9b3361

Ответ 1

Нет.

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

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

[...]

-

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

(Все предыдущие точки относятся к lvalues ​​или типам классов.)

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

int const& x = ...;

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

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

Ответ 2

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

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

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

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

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