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
本身的原始y
ness。如果我们摆脱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
(由于const
是foo::bar
方法,在这个consocu中最初const
)。考虑到问题的背景,他们是否以任何特定的方式有所不同?我认为这两个都没关系。
免责声明:我知道mutable
关键字,但这个设计(不仅有缺陷)只是一个例子。可以假设代码的作者想要禁止每一种修改vec
的方法,除了push_back
s。
你引用的段落实际上拼写出了什么是未定义的[dcl.type.cv]
除了可以修改任何声明为mutable的类成员之外,任何在其生命周期内修改const对象的尝试都会导致未定义的行为。
对非const对象的const引用/指针不会使该对象成为const对象,所有访问都是格式良好的。