为什么可以通过使用指向对象成员的指针的 const 成员函数来修改对象状态?

问题描述

为什么这段代码不会产生编译器错误

class C
{
    int _i{ 123 };
    int* ptr{ &_i };
public:
    int& i() const { return *ptr; }
};

int main()
{
    C const c;
    c.i() += 321;
    return c.i();
}

标准中有没有关于这种行为的字眼?当然,也许无论如何都没有必要指向可以直接访问的成员,但是在堆上拥有也可以视为对象的一部分的资源呢?

解决方法

在对象的构造和销毁过程中,成员不是const。这意味着您可以存储一个非常量指针,该指针指向一个成员,一旦对象被构造,该成员将成为 const。使用该指针来更改 const 对象的值是未定义的行为。引用 cppreference

通过非常量访问路径修改常量对象并通过非易失性泛左值引用易失性对象会导致未定义的行为。

并引用 [dcl.type.cv]/4

除了任何声明为 mutable 的类成员都可以修改之外,任何在其生命周期内修改 const 对象的尝试都会导致未定义的行为。