繁体   English   中英

const_cast的静态const成员

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM