请考虑以下代码:
const int x = 5;
int main() {
int* p = const_cast<int*>(&x);
*p = 10;
return 0;
}
它会导致分段错误。现在考虑一下:
int main() {
const int x = 5;
int* p = const_cast<int*>(&x);
*p = 10;
return 0;
}
工作正常。
答案 0 :(得分:5)
在这两种情况下都有未定义的行为:只有当对象实际上确实引用了一个可变对象时才允许抛出const
。您不能抛弃const
以获取作为const
对象开始生命的对象。这些对象可能存在于只读存储器中(在第一个示例中显然就是这种情况),但这并不是必需的(正如您的第二个示例所示)。
答案 1 :(得分:1)
当你使用const
时,你告诉编译器它允许更大的自由来对象做什么以换取你的承诺,你永远不会尝试改变它。当你违背这个承诺时,你就会进入未定义行为的土地。
有时编译器会以这样的方式创建代码来响应,你可以抛弃const,一切都会好的 - 就好像它从来都不是const一样。但是,这就像你的代码有效“幸运”。
将const
抛弃在一个不可变的对象上永远不会安全。
答案 2 :(得分:0)
C ++运行时有两种类型的内存,只读和读写。编译时常量被放入只读内存中,即使使用强制转换也无法更改。这里的const是硬件限制,并编写段错误。自动变量(函数范围变量)放在堆栈上,即读写存储器。这里的const是一个软件限制,绕过限制使写入成为可能。
只读与读写内存的最简单示例是字符串常量:
char *p = "string"; p[0] = 'a'; // segfault
char q[] = "string"; q[0] = 'a'; // "atring"