const_cast и ub.
-
27-09-2019 - |
Вопрос
$ 5.2.11 / 7 - «[Примечание: в зависимости от типа объекта, операция записи через указатель, lvalue или указатель на элемент данных, возникающих в результате Const_cast, который отказывается от complifier68) мая производить неопределенное поведение (7.1.5.1). ] "
Функции этого раздела (C ++ 03) удивительны для меня. Чем чувствует, что две вещи.
а) Во-первых, использование «может». Почему это «может»? Другие места в стандарте очень окончательно о неопределенном поведении
б) почему то, что отбрасывание конденсности первоначально объекта Const не сразу «неопределенное поведение». Почему требуется запись для запуска UB?
Решение
а) Во-первых, использование «может». Почему это «может»? Другие места в стандарте очень окончательно о неопределенном поведении
Не выглядеть слишком глубоко в использовании слова мая здесь. Дело в том, что отбрасывание постоянной связи в этом случае вызывает неопределенное поведение.
Стандарт C ++ использует «May» или «может» часто, как в:
1.3.12: неопределенное поведение мая Также ожидается, когда этот международный стандарт пропускает описание любого явного определения поведения.
Упор мой. По сути, стандарт использует слово «может» как в «разрешено".
б) почему то, что отбрасывание конденсности первоначально объекта Const не сразу «неопределенное поведение». Почему требуется запись для запуска UB?
Пишите триггеры UB, потому что возможно, что объекты Const могут храниться в памяти только для чтения на определенных платформах.
Другие советы
Мое понимание заключается в том, что он будет только UB, если рассматриваемый объект принципиально является объектом Const, а не указатель Const или ссылка на объект, который не был изначально Const.
Идея заключается в том, что данные, которые принципиально Const могут быть загружены в порцию памяти только для чтения, и написание этого, просто не собирается работать. Тем не менее, он гарантированно работает правильно, если рассматриваемый объект принципиально изменяется.
Бывший:
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
Так что это специально разрешено.
Для вашего первого вопроса, если что-то мая производить неопределенное поведение, то это не делает его менее неопределенным.
Для второй части я представлял, что это для совместимости. Например, C не (или не, до C99) иметь const
Ключевое слово, поэтому, если вы хотите пройти объект const к функции C, постоянная связь должна быть выброшена. Таким образом, стандарт C ++ указывает, что это допускается до тех пор, пока нет записи. Если функция C является только для чтения, постоянная связь может быть безопасно выброшена.
Даже в C ++, непоследовательный или неполный конденс-корректность тоже довольно распространен. Таким образом, мы иногда бегаем в ситуации, когда мы должны отбрасывать Const-Ness, чтобы пройти объект Const к функции, которая не модифицирует свой аргумент, но принимает его не-Const.
Я бы поверил, что это потому, что const
Объект может храниться в памяти только для чтения. Таким образом, написание на него может иметь много различных эффектов: сбой программы, неисправность сегментации или отсутствие эффекта.