2012-06-15 3 views
3

Смотрите следующее:Разве разыменовывает указатель из const_cast ALWAYS вызывает неопределенное поведение?

struct A 
{ 
    std::string* get() const 
    { 
     //return const_cast<std::string*>(&m_pObj); 
     return &const_cast<A*>(this)->m_pObj; 
    } 

    std::string m_pObj; 
}; 

ли разыменования const_cast из this UB? Есть ли время разыгрывать результат от const_cast до констатации указателя далеко не invoke UB?

(я знаю, что в приведенном выше примере это плохая практика, плохой дизайн, и может быть решена с изменяемым - это не точка)

ответ

9

ли разыменования const_cast этого UB? Есть ли время разыменования результата из const_casting, что константа указателя далеко не вызывает UB?

Не всегда, только если объект является Const (экземпляр A является const A x;) и разыменовать используется для изменения данных. Если он используется только для , прочитанного, это не будет неопределенным поведением, если объект не является константой (может быть, вообще нет, может быть, const-ссылкой на неконстантный объект), это тоже не будет UB.

3

Нет, это только UB, если объект ссылки был объявлен const первоначально и вы впоследствии модифицируете данные, полученные литой (§5.2.11/7 и §7.1.6.1/4). Следующее является законным:

A a; 
a.get()->clear(); 

в то время как это не является (и, следовательно, UB):

A const a; 
a.get()->clear(); 
+4

Пока разыменование не используется для * изменения * объекта, нет UB. Это: 'A const a; std :: cout << * a.get(); 'отлично, но' a.get() -> clear(); 'is not. –

+0

@ Давид да; см. обновление. О, и я предпочитаю ваш пример ('-> clear()') для моего (разыменовать + изменить '[0]'), поэтому я украл его, надеюсь, вы не против. –

+0

Нет проблем :) +1 –

1

Количество А именно:

5.2.2 Вызов функции

5 [Примечание: функция может изменять значения своих неконстантных параметров, но эти изменения не могут повлиять на значения аргументов, кроме тех случаев, когда параметр имеет ссылочный тип (8.3.2); если ссылка относится к типу const-qual, const_cast необходимо использовать для отбрасывания константы, чтобы изменить значение аргумента . Если параметр является ссылочным типом константы, то вводится временный объект, если необходимо (7.1.6, 2.14, 2.14.5, 8.3.4, 12.2). Кроме того, можно изменять значения непостоянных объектов через параметры указателя. -end примечание]

Однако

5.2.11 Const отливать

12 [Примечание: некоторые преобразования, которые включают только изменения в сорте-квалификации не может быть сделано с помощью const_cast. Например, преобразования между указателями на функции не рассматриваются, поскольку такие преобразования приводят к значениям , использование которых вызывает неопределенное поведение.По тем же причинам конверсии между указателями на элемент функционируют, и в частности, преобразование от указателя на функцию-член-член к указателю на функцию неконстантного члена не покрывается. -end note]

0

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

Реально, что компилятор довольно редко выполняет что-то, что будет нарушено const_cast-ing, но теоретически это возможно.

+0

Какая из предыдущих ответов неправильная? Все они сказали, что попытка изменить объект const - это неопределенное поведение. Исключение const абсолютно законно, всегда, и изменение объекта по результатам актерского состава также является законным (и четко определено), если сам объект не является const. –

+0

Вы правы (я удалил заявление). Я читал их слишком быстро. Все начиналось с «нет» и «не всегда», что казалось неправильным, но, читая лучшее, я вижу, что они адекватно его оценили. Извиняюсь. –

Смежные вопросы