何时可以使用 const_cast 删除 const 时修改值
When is it ok to modify a value when you remove const with const_cast?
根据 §7.1.5.1/4:
除了可以修改任何声明为可变 (7.1.1( 的类成员之外,任何在其生存期 (3.8( 期间修改 const 对象的尝试都会导致未定义的行为。
所以我的问题变成了:一个对象什么时候是常量对象?
特别是,非常量对象中的常量成员是否被视为常量对象?
class Foo {
const Bar bar;
void replaceBar(Bar bar2) {
*(const_cast<Bar *>&bar) = bar2; // Undefined behavior?
}
}
出现这是因为我有一个不可变的类(所有字段都是 const(,但我想有一个移动构造函数,它在技术上修改传入的值。 在这种情况下,我可以接受"作弊",因为它不会破坏逻辑不变性。
简单的规则是:如果原始对象不是常量,则可以抛弃恒常性。因此,如果你有一个非cont对象,比如说,你将对它的const引用传递给一个函数,那么抛弃函数中的常量是合法的。在你的例子中,原始对象是恒量,所以抛弃恒常性是未定义的行为。
让我们做一个完整的例子:
struct Bar { int x; };
struct Foo {
const Bar bar;
Foo( int x ):bar(x) {}
void replaceBar(Bar bar2) {
*(const_cast<Bar *>&bar) = bar2; // Undefined behavior?
}
};
现在,让我们打破世界。
int main() {
Foo f(3);
Bar b = {2};
f.replaceBar(b);
std::cout << f.bar.x << "n";
}
以上可以而且可能应该输出 3,因为const
对象Bar
是用 x=3
创建的。 编译器可以并且应该假定const
对象在其生存期内保持不变。
让我们打破更多世界:
struct Bar {
int* x;
Bar(int * p):x(p) {}
~Bar(){ if (x) delete x; }
Bar(Bar&& o):x(o.x){o.x=nullptr;}
Bar& operator=(Bar&& o){
if (x) delete x;
x = o.x;
o.x = nullptr;
}
Bar(Bar const&)=delete;
Bar& operator=(Bar const&)=delete;
};
struct Foo {
const Bar bar;
Foo( int* x ):bar(x) {}
void replaceBar(Bar bar2) {
*(const_cast<Bar *>&bar) = bar2; // Undefined behavior?
}
};
现在,同一个游戏可能会导致编译器删除某些内容两次。
int main() {
int* p1 = new int(3);
Foo f( p1 );
Bar b( new int(2) );
f.replaceBar(std::move(b));
}
并且编译器会在replaceBar
内删除一次p1
,并且应该在main
结束时删除它。 它可以做到这一点,因为您保证f.bar.x
在其范围结束之前保持不变(const
(,那么您在 replaceBar
中违反了该承诺。
现在,这只是编译器有理由做的事情:一旦你修改了声明为const
的对象,编译器就可以做任何事情,因为你已经调用了未定义的行为。 鼻魔,时间旅行 - 任何东西都可以争夺。
编译器使用某些行为未定义(即不允许(的事实进行优化。
相关文章:
- 具体来说,标准在哪里规定修改 const 对象是未定义的行为?
- C++ 为什么const X&可以通过功能进行修改?
- 修改C++中的"Const Char Pointers"
- 修改数据是否由 const shared_ptr&Ok 传递?
- const 方法使用引用修改对象
- 为什么 QObject::d isconnect(const QMetaObject::Connection &connection) 采用 const 参数并打算修改它?
- 有条件地传递修改后的副本而不是const原始副本变得丑陋
- 为什么当返回类型为 const 时可以修改返回值
- 为什么我可以在C 11中使用const函数修改类
- 是否允许在常量定义的对象上丢弃 const 只要它没有实际被修改?
- C++17:是编译器为(静态存储持续时间)const引用绑定创建的可修改的临时对象(和存储)
- C++ 可以修改 const 对象的成员
- const静态方法修改值
- 通过 const_cast 删除 const 并调用不修改结果对象的非 const 函数是否安全?
- 使用修改'scratchpad'变量的 const 函数是否正确?
- 从const char*转换为char*会修改VC++中的数据
- 如果类 A 修改其构造参数,我可以使用常量参数初始化 const A 吗?
- 重写 const 函数以修改 C++ 中的类变量
- 修改 const 方法中的 pointee 值
- 如何修改/更新通过 const 引用传递的对象的内部状态