const_cast и UB - PullRequest
       63

const_cast и UB

5 голосов
/ 28 октября 2010

$ 5.2.11 / 7 - "[Примечание: в зависимости от тип объекта, операция записи через указатель, lvalue или указатель к члену данных в результате const_cast, который отбрасывает const-qualifier68) может производить неопределенное поведение (7.1.5.1). ] "

Формулировки этого раздела (C ++ 03) меня удивляют. Что удивительно, так это две вещи.

а) Во-первых, использование «может». Почему это «может»? Другие места в Стандарте очень точно определяют неопределенное поведение

б) Почему отбрасывание константности изначально константного объекта не является «неопределенным поведением». Почему для запуска UB требуется запись?

Ответы [ 4 ]

4 голосов
/ 28 октября 2010

а) Во-первых, использование «может».Почему это «может»?Другие места в Стандарте весьма определенно относятся к неопределенному поведению

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

Стандарт C ++ часто использует «может» или «может», как в:Поведение может также ожидаться, когда в этом международном стандарте опущено описание какого-либо явного определения поведения.

Выделение мое.В основном, в стандарте используется слово «может», так как в « разрешено ».

б) Почему отбрасывание константности изначально константного объекта не является прямымпрочь «неопределенное поведение».Почему для запуска UB необходима запись?

Запись запускает UB, поскольку на определенных платформах константные объекты могут храниться в постоянной памяти.

3 голосов
/ 28 октября 2010

Для вашего первого вопроса, если что-то может вызвать неопределенное поведение, то это не делает его менее неопределенным.

Во второй части, я думаю, это из соображений совместимости.Например, C не имеет (или не имел до C99) ключевое слово const, поэтому, если вы хотите передать const-объект в функцию C, константность должна быть отброшена.Таким образом, стандарт C ++ указывает, что это разрешено, если не выполняется запись.Если функция C доступна только для чтения, константность может быть безопасно отброшена.

Даже в C ++ непоследовательная или неполная правильность констант также довольно распространена.Поэтому мы иногда сталкиваемся с ситуациями, когда нам приходится отбрасывать константу, чтобы передать константный объект в функцию, которая не изменяет свой аргумент, но принимает его как неконстантный.

3 голосов
/ 28 октября 2010

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

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

Ex:

const int  x = 4;
const int *y = x;

*const_cast<int*>(x) = 3; // UB - the pointed-to object may 
                          // be in read-only memory or whatever.

int        a = 7;
const int *b = a;

*const_cast<int*>(b) = 6; // Not UB - the pointed-to object is 
                          // fundamentally mutable.

Для комментария ниже, потому что код выглядит ужасно в комментариях:

В §7.1. 5.1 / 4 стандарта приведен пример:

int i = 2;
const int * cip; // pointer to const int
cip = &i;        // OK: cv-qualified access path to unqualified
...
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

Так что это специально разрешено.

1 голос
/ 28 октября 2010

Я полагаю, это потому, что объект const может быть сохранен в постоянной памяти. Таким образом, запись в него может иметь множество различных эффектов: сбой программы, ошибка сегментации или отсутствие эффекта.

...