2011-11-23 6 views
18

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


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

Приемлемо ли const_castconst ссылка, которая связана с временным объектом?

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

Мой ответ был, что я спросил a similar question ранее, где консенсус, казалось, что сами по себе являются временных сути не const, и, таким образом, что вы можете сбросила const -ness для ссылки у вас есть к ним, и изменить их результат. И, пока этот оригинальный 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 

Я прав?


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

+0

@Mark: О, буквально, возможно, был плохим выбором. Я теперь сделал это нелиберальным для этого вопроса. –

+0

Я собирался сказать, что в этом коде не было времен. К счастью, я обновил страницу перед тем, как сделать это :) – Gorpik

+0

afaik (но я не могу найти его в стаддаре), он говорит что-то вроде «когда он был объявлен как const, тогда вы не можете отбросить константу» ... так что вопрос , является литом, объявленным как const? Я так не думаю, так как это приводит к временному объекту, и так объявляется как const? Я понятия не имею, но мои мужества говорят: no – PlasmaHH

ответ

8

No.

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

Ссылка на тип « CV1 Т1” инициализируется выражением типа „CV2 Т2“ следующим образом:

[...]

-

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

(. Все заботы вышеуказанных пунктов либо lvalues ​​или типа класса)

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

int const& x = ...; 

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

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

+0

Разве это не означает, что 3.10/9 и 8.5.3 противоречат друг другу? –

+2

@ TomalakGeret'kal Не совсем. В § 3.10/9 рассказывается о значениях и значениях. Выражение типа '3' или' int (3) 'является rvalue. §8.5.3 рассказывает о том, как инициализировать ссылку; ссылки никогда не являются значениями и должны ссылаться на объект . Поэтому в §8.5.3 говорится, что компилятор создает временный объект , инициализированный rvalue, и связывает ссылку на это. Вы не получаете ссылку на целочисленный литерал, потому что таких вещей не существует; вы получаете ссылку на невидимый, неназванный объект , который имеет тип ссылки (а не инициализатор ). –

+0

Ах! Я вижу ................. Интересно. Затем я соглашаюсь с вашим заключением, и я полагаю, что это означает, что продление срока жизни временного периода приводит к неудачному следствию, что мы не можем их модифицировать. –

1

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

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

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

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

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

+0

Я не могу найти что-либо в 8.5.3/5, что указывает на то, что какое-либо временное на RHS не должно проваливаться в статью Джеймса. Можете ли вы продемонстрировать, что сценарий отличается, когда я «явно создаю временный [я]»? –

+1

@Tomalak Geret'kal: Ну, для класса типа 'T', если я просто делаю' const T & r = T() ', у меня есть шанс, что ссылка будет привязана непосредственно к моей' T() '(говорит 8.5.3/5), что не является константой. В этом случае совершенно законно отбрасывать константу и изменять объект. – AnT

+0

8.5.3/5 огромен, и, как я уже сказал, я не могу найти дедуктивные шаги, которые вы используете. –