给出以下 C++ 代码:
#include <iostream>
int main()
{
const int i = 1;
*const_cast<int*>(&i) = 1; // Not allowed but doesn't do anything?
std::cout << i << "\n";
}
问题:上面的代码是否调用了UB(未定义的行为)?我知道抛弃 const 并为
i
分配一个新值会导致 UB,因为我们不允许更改 const 变量的值。然而,在上面的代码中,我实际上并没有改变 i
的值 - 那么,这仍然是 UB 吗?
编辑:为什么问题被关闭?它明确地涉及与所谓的重复问题不同的用例,即如果您实际上不更改 const 变量的值会发生什么。是的,相同的规则可能适用于这个用例,所以它仍然是 UB,但这并不明显。
是的。还是UB。
尝试更改 const 变量是 UB,而不仅仅是分配一个new值。
来自 N4296,第 1.9 节,第 4 段:
本国际标准中将某些其他操作描述为未定义(例如,尝试修改
对象的效果)。const
问题:上面的代码是否调用了UB(未定义行为)?
是的。
但是,在上面的代码中,我实际上并没有改变i的值
这正是您通过指向 i
的指针分配给间接结果时所做的事情。
只是因为它是未定义的,所以不能保证程序在分配值时会按照您期望的方式运行。
const_cast
适用于当您拥有对
不是
const
的变量的 const 引用时。基本上,如果您知道正在引用非常量对象,那么这是一种作弊方法。我认为
const_cast
的“好”(老实说,我从来不认为它实际上是好的)示例是指当你有一个可以正常修改自身的内部结构,但从外部访问时将其自身呈现为 const
(一种方法)让事物从外部看起来是只读的)。如果您尝试修改声明为 const 的实际数据,那么它是未定义的,并且根据您正在使用的系统将会更改错误。有些环境可能会触发段错误,有些环境不会执行任何操作(只读内存,忽略写入),有些环境可能会更改数据(例如,如果程序的数据完全加载到正常的可写内存中)。
expr.const.cast是的,它仍然是 UB,因为你在这里按照
: 进行写入操作
[注 2: 根据对象的类型,通过指针、左值或指向由 const_cast 产生的数据成员的指针进行写入操作抛弃 const 限定符 59 可能会产生未定义的行为([dcl.type 。简历])。 — 尾注]
(强调我的)
基本上只要你在这里进行写操作,就会出现未定义的行为。