Не приведено ли приведение указателя к константному указателю и приведение обратно к исходному типу? - PullRequest
1 голос
/ 30 марта 2019

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

int i = 0;
int * pi = &i;
const int * const_pi = const_cast<const int*>(pi);
int * non_const_pi = const_cast<int*>(const_pi);
*non_const_pi = 0;
*non_const_pi = 1;
int j = *non_const_pi;

Есть ли неопределенное поведение? Если таковые имеются, где они происходят? Может ли компилятор предположить, что non_const_pi приведен из константного указателя и не выполнять никаких изменений?

Ответы [ 2 ]

5 голосов
/ 30 марта 2019

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

Это недоразумение.

Указатели на константное приведение никогда не приводят кнеопределенное поведение.Разыменование указателя не-const, полученного путем const_cast -ing указателя const на объект const, также не является неопределенным поведением, если исходный объект используется в режиме только для чтения.Это не определенное поведение, если вы пытаетесь записать объект.

int const i = 10;
int const* p1 = &i;
int* p2 = const_cast<int*>(p1);  // OK.
std::cout << *p2;                // Still OK.
*p2 = 20;                        // Not OK.

Учитывая это, ваш второй блок кода в порядке.Не существует неопределенного поведения, так как исходный объект не является const объектом.

С Стандарт, Раздел 5.2.11, Выражения / Константное приведение :

Результат указателя const_cast относится к исходному объекту.

4 голосов
/ 30 марта 2019

Нет, это не UB. Только при попытке изменить объект const через неконстантный путь доступа получается UB. В этом случае non_const_pi указывает на неконстантный объект i на самом деле, тогда изменение через него - это нормально.

В стандарте есть точный пример, [dcl.type.cv] / 4 :

... любая попытка изменить ([expr.ass], [expr.post.incr], [expr.pre.incr]) константный объект ([basic.type.qualifier]) во время его время жизни ([basic.life]) приводит к неопределенному поведению. [Пример:

...

int i = 2;                              // not cv-qualified
const int* cip;                         // pointer to const int
cip = &i;                               // OK: cv-qualified access path to unqualified
*cip = 4;                               // ill-formed: attempt to modify through ptr to const

int* ip;
ip = const_cast<int*>(cip);             // cast needed to convert const int* to int*
*ip = 4;                                // defined: *ip points to i, a non-const object
...