[英]const_cast of a static const member
以下代码使用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;
}
我认为相关的引用是:
N3242的第7.1.6.1(4)段:
除了可以修改任何声明为mutable的类成员之外,任何在其生命周期内修改const对象的尝试都会导致未定义的行为。
这些例子说明了使用const_cast
的观点。 正如James所指出的那样:引用可以在C ++ 03标准的§7.1.5中找到。
一点点阐述:当某些东西被声明为const
时,该语言规则允许编译器使用只读内存(如果它在目标体系结构上可用)。 如果没有这个规则, const
-ness总是可以在不担心任何后果的情况下被丢弃,并且使用它只会是开发人员纪律的问题。 它的方式至少可以告诉人们他们正在调用UB,这通常是一个很好的威慑。 const_cast
本身具有较小的相关性,因为如何欺骗编译器让你操纵const
对象并不重要。
5.2.11.7:
根据对象的类型,通过指针,左值或指向数据成员的指针的写入操作可能会产生未定义的行为(7.1.5.1)
在您的情况下,您正在尝试修改只读段中的数据。
因为您不允许修改声明为const的变量。
我没有解决实际问题的方法。 我只能说,不要使用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;
}
仅仅因为你抛弃了const,并不意味着你会成功写入那个记忆。
const_cast<T>
所做的就是从编译器的角度去除变量的常量。 这让编译器继续发出代码来写入变量。 但是在运行时,如果编译器/链接器碰巧将变量放在只读内存中,那么无论你如何投射它,硬件都会阻止你在那里写。
基本上,如果变量声明为const
,则允许编译器将结果发送到只读内存。 获取const
对象的指针/引用,然后使用const_cast
删除const
可能导致未定义的行为。
一般来说,如果引用的对象是非const
,那么使用const_cast
是安全的(即使你的指针/引用是const
)。
问题是这一行:
static int const v;
因为你声明它是const,const_cast导致一个未定义的行为 - 在你的情况下你很幸运得到总线错误(这是我的系统上的分段错误)。
声明它是非const的,你可以毫无问题地调用const_cast。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.