是否在 const 方法未定义行为中修改非常量对象的非可变成员?

Is modifying non-mutable member of non-const object in const method Undefined Behaviour?

dcl.type.cv 提供了一个有趣的例子:

For another example,

struct X {
  mutable int i;
  int j;
};
struct Y {
  X x;
  Y();
};

const Y y;
y.x.i++;                                // well-formed: mutable member can be modified
y.x.j++;                                // ill-formed: const-qualified member modified
Y* p = const_cast<Y*>(&y);              // cast away const-ness of y
p->x.i = 99;                            // well-formed: mutable member can be modified
p->x.j = 99;                            // undefined: modifies a const member

这表明,通过 const_cast,可以修改 const 合格对象的 mutable 成员,而不能使用非 mutable会员。

据我了解,这是因为 y 本身的原始 constness。如果我们去掉 mutable 关键字,const 限定符 y,但修改 const 方法中的字段,会发生什么情况?

示例如下:

#include <vector>

struct foo {
    std::vector<int> vec{};

    void bar() const {
        auto& raw_ref = const_cast<std::vector<int>&>(vec);
        raw_ref.push_back(0);       // ok?

        auto* raw_this = const_cast<foo*>(this);
        raw_this->vec.push_back(0); // ok?
    }
};

int main() {
    foo f{};
    f.bar();
}

它是否表现出未定义的行为?我认为它不会,因为我们正在修改最初非 const,而是在 const 上下文中。

此外,请注意我提供了两种修改 vec 的方法。一个具有非 const 引用,一个具有指向 this 的非 const 指针(由于 foo::barconst 方法)。考虑到问题的背景,它们在任何特定方面有什么不同吗?我假设两者都可以。

免责声明:我知道 mutable 关键字,但这个设计(不仅有缺陷)只是一个例子。可以假设代码的作者想要禁止每一种修改 vec 的方式,除了 push_backs.

您引用的段落实际上准确地说明了未定义的内容[dcl.type.cv]

Except that any class member declared mutable can be modified, any attempt to modify a const object during its lifetime results in undefined behavior.

非 const 对象的 const reference/pointer 不会使该对象成为 const 对象,您的所有访问都是合式的。