首页 > 解决方案 > 是否在 const 方法未定义行为中修改非 const 对象的非可变成员?

问题描述

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

再举一个例子,

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,可以修改合格对象mutable的成员const,而您不能对非mutable成员执行此操作。

据我了解,这是因为它本身的原始consty。如果我们去掉mutable关键字const限定符 fot 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引用的,一个是非const指针的(由于是一种方法this,最初在这个上下文中)。考虑到问题的上下文,它们是否有任何特定的不同?我会假设两者都可以。constfoo::barconst

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

标签: c++constantslanguage-lawyerconst-cast

解决方案


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

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

指向非 const 对象的 const 引用/指针不会使该对象成为 const 对象,您的所有访问都是格式正确的。


推荐阅读