提问人:asimes 提问时间:11/16/2023 最后编辑:asimes 更新时间:11/16/2023 访问量:174
const_cast与可变和未定义的行为
const_cast vs mutable and undefined behavior
问:
编辑:我在这里编辑了代码以不使用指针,因为有太多不相关的评论
#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_cast
那么我的问题是,是否存在具有成员的对象会导致未定义行为的情况const
mutable
答:
字段从来都不是常量,因此永远不能使用const_cast调用 UB。这是不同的行为,因为理论上 #1 可以将索引放在 rom 中mutable
评论
foo
const
mutable
const
mutable
mutable
const
const
mutable
const 对象的可变成员子对象本身不是 const 对象,并且 const 对象的任何特殊规则(例如不允许修改它)都不适用于它。
以递归方式,包含完整对象和该子对象的其他不可变子对象仍然是常量对象,因此不能修改。
const 对象的定义可以在标准的 [basic.type.qualifier/1.1] 中找到:
(1.1) const 对象是 const 对象的类型对象或不可更改的子对象。
const T
因此,修改成员子对象或其任何子对象总是可以的,即使包含对象是 ,但这仅适用于可变成员。是否涉及任何内容无关紧要。mutable
const
const_cast
但是,这仅涵盖可变子对象的实际修改,即对自身或其(标量)子对象之一的内置赋值。仍然不允许通过 placement-new 将可变子对象替换为新对象。关于替换 const 对象的相关规则是,任何新对象都不能放置在任何已经或将被自动、静态或线程本地存储持续时间的 const-complete 对象占用的存储中。在您的例子中,是一个 const 对象和一个完整的对象。它具有自动存储持续时间,可变子对象占用其部分存储。bar
评论