Является ли const_cast (this) с операцией записи неопределенным поведением, если фактический объект не является const? - PullRequest
3 голосов
/ 11 июля 2019

Мой вопрос вдохновлен этим ответом на другой мой вопрос: https://stackoverflow.com/a/56989169/2492801.

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

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

Для меня важно знать, что нужно знать, как бороться с проблемой, описанной в моем другом вопросе. Спасибо!

Ответы [ 3 ]

8 голосов
/ 11 июля 2019

Это не неопределенно.Это именно то, для чего const_cast.Пока сам объект не является const, вы можете отбросить его с помощью const_cast и делать с ним те же вещи, что и с указателем не const.

Обратите внимание, что const_castобычно считается запахом кода и может указывать на плохой дизайн.


Как гласит стандарт :

В теле не static ([class.mfct]) функция-член, ключевое слово this - это значение, значение которого является указателем на объект, для которого вызывается функция.Тип этого в функции-члене класса X: X*.Если функция-член объявлена ​​как const, типом этого является const X*, если функция-член объявлена ​​volatile, типом этого является volatile X*, а если функция-член объявлена ​​const volatile, типэто const volatile X*.

Тип this в вашем случае const X*, даже если сам объект не является const.


Стандарт говорит об этом о const_cast:

Для двух похожих типов T1 и T2 значение типа T1 может быть явно преобразовано в типT2 с использованием const_­cast.Результат const_­cast относится к исходной сущности.

Таким образом, приведение от const X* к X* также допустимо.


Наконец, он говорит (хотя и в примечании):

[Примечание: в зависимости от типа объекта, операция записи через указатель, lvalue или указатель на элемент данных, получаемый в результате const_castто, что отбрасывает const -квалификатор, может привести к неопределенному поведению ([dcl.type.cv]).- конец примечания]

И [dcl.type.cv] сообщает нам :

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

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


Извините, Angew.

0 голосов
/ 11 июля 2019

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

Где это может пойти не так, если у вас естьагрегатный объект с «приемлемыми» методами-членами.Нет конструкторов, деструкторов, виртуалов, изменяемых членов, членов, которые сами не являются агрегатами, и не могут быть его производными.

Экземпляр такого объекта может быть объявлен в статическом пространстве как константа, а компилятор может создать экземплярэтот объект в предопределенный неизменяемый блок памяти.Выполнение const_cast для этого объекта и попытка его изменения либо с помощью глобальной функции, либо с помощью функции-члена вызовет «неопределенное поведение», возможно, исключение, возможно, неисправимую ошибку, почти наверняка приводящую к завершению программы.

0 голосов
/ 11 июля 2019

const_cast только изменяет тип, но не изменяет двоичное представление этого указателя. Таким образом, поведение изменяется только в том случае, если вызываемая функция-член переопределена. Таким образом, ответ на ваш вопрос - НЕТ.

...