以下代码使用GCC(4.2-4.6)和Clang(2.1)编译得很好,但是当我运行可执行文件时,它给出了“总线错误:10”。我不明白原因。
#include <iostream>
struct A
{
static int const v;
A() { ++*const_cast<int *>(&A::v); }
};
int const A::v = 0;
int main(int argc, char * argv[])
{
A a, b, c;
std::cout << a.v << std::endl;
return 0;
}
答案 0 :(得分:12)
我认为相关的引用是:
来自N3242的§7.1.6.1(4):
除了声明可变的任何类成员都可以修改,任何 尝试在其生命周期内修改const对象 未定义的行为。
这些例子说明了使用const_cast
的观点。正如James指出的那样:引用可以在C ++ 03标准的第7.1.5节中找到。
一点阐述:当声明某些内容const
时,该语言规则允许编译器使用只读内存(如果它在目标体系结构上可用)。如果没有这个规则const
- 可以随时提供,而不必担心任何后果,使用它只会是开发人员的纪律问题。它的方式至少可以告诉人们他们正在调用UB,这通常是一个很好的威慑。 const_cast
本身具有较小的相关性,因为如何欺骗编译器让你操纵const
对象并不重要。
答案 1 :(得分:6)
5.2.11.7:
根据对象的类型,通过写入操作 指针,左值或指向const_cast的数据成员的指针 抛弃一个const限定符)可能会产生未定义的行为 (7.1.5.1)
在您的情况下,您正在尝试修改只读段中的数据。
答案 2 :(得分:4)
因为你不允许修改声明为const的变量。
答案 3 :(得分:2)
我没有实际问题的解决方案。我只能说,不要使用const_cast
,除非意图从非const成员函数调用const成员函数,并且“const_cast”调用const结果(使其成为非const的可变结果)成员函数)。
但我有一项改进设计的建议:
class A
{
private:
static int v;
public:
A() { ++v; }
static int get_v() { return v; }
};
int A::v = 0;
int main(int argc, char * argv[])
{
A a, b, c;
std::cout << a.get_v() << std::endl;
return 0;
}
答案 4 :(得分:2)
仅仅因为你抛弃了const,并不意味着你会成功地写入那段记忆。
const_cast<T>
所做的就是从编译器的角度去除变量的常量。这让编译器继续发出代码来写入变量。但是在运行时,如果编译器/链接器碰巧将变量放在只读内存中,那么无论你如何构建它,硬件都会阻止你写入它。
答案 5 :(得分:2)
基本上,如果变量声明为const
,则允许编译器将结果发送到只读内存。获取const
对象的指针/引用,然后使用const_cast
删除const
可能会导致未定义的行为。
一般情况下,如果引用的对象不是const_cast
,那么使用const
是安全的(即使你的指针/引用是const
)。
答案 6 :(得分:1)
问题在于这一行:
static int const v;
因为你声明它是const,const_cast导致一个未定义的行为 - 在你的情况下你很幸运得到总线错误(这是我的系统上的分段错误)。
声明它为非const,你可以毫无问题地调用const_cast。