const_cast的静态const成员

时间:2011-08-08 19:30:05

标签: c++ static const member const-cast

以下代码使用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;
}

7 个答案:

答案 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。