常数值变更

时间:2018-10-08 21:16:59

标签: c++ const undefined-behavior

假设我有一个结构定义:

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吗?

2 个答案:

答案 0 :(得分:10)

[dcl.type.cv] p4:

  

除了任何声明为mutable([dcl.stc])的类成员可以   已修改,任何修改尝试([expr.ass],[expr.post.incr],   [expr.pre.incr])常量对象([basic.type.qualifier])   寿命([basic.life])导致行为不确定。

[basic.type.qualifier] p1:

  

常量对象const T类型的对象或该对象的不可更改子对象。

c.z是const对象,因为它是c的不可更改子对象。您的代码尝试在其生命周期内对其进行修改。因此,该代码具有未定义的行为。

答案 1 :(得分:0)

foo函数本身就可以了,因为const之类的T::foo() const成员函数只是表明this的类型为const *T;这样,(非常量)成员指向同一对象这一事实就无关紧要。

首先将对象c声明为const。因此,UB通过任何代码(包括(本身正确的)成员函数c)更改foo的内容。