Изменение постоянной стоимости
Предположим, у меня есть определение структуры:
struct thing
{
thing* x;
int z;
thing() : x(this), z(0) {}
void foo() const
{
this->x->z++;
}
};
Обратите внимание, что я создаю изменяемый указатель на себя (злой смех)
И тогда я могу использовать это позже следующим образом:
int main()
{
const thing c;
c.foo();
assert(c.z == 1);
c.foo();
assert(c.z == 2);
return c.z;
}
И, как вы видите, кажется, что я могу изменить постоянную ценность... это UB?
Ответы
Ответ 1
[Dcl.type.cv] р4:
За исключением того, что любой член класса, объявленный mutable
([dcl.stc]), может быть изменен, любая попытка изменить ([expr.ass], [expr.post.incr], [expr.pre.incr]) объект const ([ basic.type.qualifier]) в течение своего жизненного цикла ([basic.life]) приводит к неопределенному поведению.
[Basic.type.qualifier] p1:
Объектом const является объект типа const T
или не изменяемый подобъект такого объекта.
cz
- объект const, потому что он является не изменяемым подобъектом c
. Ваш код пытается изменить его в течение своей жизни. Из этого следует, что код имеет неопределенное поведение.
Ответ 2
foo
-function само по себе было бы хорошо, так как const
функции - члены, такие как T::foo() const
просто указать, что this
имеет тип const *T
; То, что a (не const) член указывает на один и тот же объект, не имеет значения.
Однако объект c
на первом месте объявляется как const. Таким образом, UB изменяет содержимое c
на любой код, включая функцию (per se correct) member foo
.