在const方法中修改非const对象的非可变成员Undefined Behavior?

问题描述 投票:2回答:1

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成员那样做。

据我所知,这是因为const本身的原始yness。如果我们摆脱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参考和一个非const指针this(由于constfoo::bar方法,在这个consocu中最初const)。考虑到问题的背景,他们是否以任何特定的方式有所不同?我认为这两个都没关系。

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

c++ const language-lawyer const-cast
1个回答
3
投票

你引用的段落实际上拼写出了什么是未定义的[dcl.type.cv]

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

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

© www.soinside.com 2019 - 2024. All rights reserved.