编辑:我编辑了这里的代码,不使用指针,因为有太多无关的评论
#include <iostream>
struct Foo {
Foo(const int a) : total(a) {}
int index = 0;
const int total;
};
struct Bar {
Bar(const int a) : total(a) {}
mutable int index = 0;
const int total;
};
int main() {
const Foo foo(3);
for (
;
foo.index < foo.total;
const_cast<Foo*>(&foo)->index++ // 1. Undefined behavior because foo is const
)
std::cout << "Foo " << foo.index << std::endl;
const Bar bar(3);
for (
;
bar.index < bar.total;
bar.index++ // 2. Not undefined behavior because of mutable?
)
std::cout << "Bar " << bar.index << std::endl;
return 0;
}
字符串
据我所知,标记为// 1. Undefined behavior because foo is const
的行是未定义的行为,因为foo
是const
对象,而const_cast
无论如何都被用于修改该对象
然而,我不确定是否有任何可能的未定义行为与标记为// 2. Not undefined behavior because of mutable?
的行有关。
那么我的问题是,是否存在具有mutable
成员的const
对象会导致未定义行为的情况
2条答案
按热度按时间eqoofvh91#
一个
mutable
字段永远不是const,因此永远不能用const_cast调用UB。这是不同的行为,因为理论上#1可以在rom中放置索引。piv4azn72#
const对象的可变成员子对象本身不是const对象,并且不适用于const对象的任何特殊规则,例如不允许修改它。
递归地,包含完整对象和该子对象的其他不可变子对象仍然是常量对象,因此不能被修改。
(1.1)const object 是
const T
类型的对象或const对象的不可变子对象。所以修改
mutable
成员子对象或它的任何子对象总是可以的,即使包含对象是const
,但这只适用于可变成员。是否涉及任何const_cast
都无关紧要。然而,这只涵盖了可变子对象的实际修改,也就是说,内置赋值给自身或它的一个(标量)子对象。仍然不允许的是通过placement-new用新对象 * 替换 * 可变子对象。关于替换const对象的相关规则是,任何新对象都不能放置在任何已经或将要被const占用的存储中-自动、静态或线程本地存储持续时间的完整对象。在您的示例中,
bar
是一个const对象和完整对象。它具有自动存储持续时间,可变子对象占用其部分存储。