通过非const指针修改const

时间:2010-03-24 14:46:05

标签: c++ pointers casting const-correctness

我对以下代码中发生的事情感到有点困惑:


const int e = 2;

int* w = ( int* ) &e;          // (1) cast to remove const-ness
*w = 5;                        // (2)

cout << *w << endl;            // (3) outputs 5
cout << e << endl;             // (4) outputs 2

cout << "w = " << w << endl;   // (5) w points to the address of e
cout << "&e = " << &e << endl;

在(1)中,w指向e的地址。在(2)中,该值变为5.但是,当显示* w和e的值时,它们的值不同。但是如果你打印w指针和&amp; e的值,它们就有相同的值/地址。

为什么e仍然包含2,即使它被改为5?他们存放在一个单独的位置?还是暂时的?但是为什么w所指出的价值仍然是e?

的地址

6 个答案:

答案 0 :(得分:17)

正如我在评论中所说,一旦修改了const值,你就处于未定义的行为状态,所以谈论正在发生的事情并没有多大意义。但到底是怎么回事......

cout << *w << endl;            // (3) outputs 5
cout << e << endl;             // (4) outputs 2

猜测,*w正在运行时进行评估,但e被视为编译时常量

答案 1 :(得分:8)

我怀疑你正在绊倒编译器。它并不指望你用e玩肮脏的技巧,所以当它看到这条线时:

cout << e << endl;

它只是插入值2而不是查找实际值。您可以通过查看程序的反汇编来验证(或反驳)。

答案 2 :(得分:4)

我猜测编译器已优化了值输出。它看到e是const(因此,理论上它不能改变)并且将cout << e << endl;更改为cout << 2 << endl;。但是,e仍然必须存在,因为w使用了w,因此cout正确获取其地址并修改其值,但您在const中看不到

故事的道德 - 只在您真正想要const时声明事物const。抛弃{{1}}并不是一个好主意。

答案 3 :(得分:3)

我唯一能想到的是编译器有一些如何优化代码的方式,即使为e指定内存,对e的任何引用都被替换为值2

如此有效(影响?)注释(4)中的行被“优化”为

cout << "2" << endln;

答案 4 :(得分:2)

我猜编译器使用constness来优化变量并在代码中插入一个固定值。

答案 5 :(得分:1)

C ++ 14标准的[dcl.type.cv] / 4节(早期标准也有类似的文字)涵盖了这一点:

  

除了可以修改声明为mutable的任何类成员之外,任何在其生命周期内修改const对象的尝试都会导致未定义的行为。

e是一个const对象,*w = 5;尝试修改该对象,因此结果为undefined behavior