C++ 通过非常量指针修改常量

C++ 通过非常量指针修改常量,c++,pointers,casting,const-correctness,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

我有点困惑以下代码中发生了什么:


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指针和&e的值,则它们具有相同的值/地址


为什么e仍然包含2,即使它被更改为5?它们是否存放在单独的位置?还是临时的?但是为什么w所指的值仍然是e的地址呢?

我怀疑你搞错了编译器。它不希望你对e耍卑鄙的把戏,所以当它看到这句台词时:

cout << e << endl;

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

我唯一能想到的是编译器对代码进行了一些优化,使对e的任何引用都被替换为值2,即使它为e分配了内存

因此,实际上(影响?)注释(4)中的行被“优化”为

cout << "2" << endln;

cout我猜编译器已经优化了值输出。它看到,
e
是常量(因此,它在理论上不能改变)并且改变了
cout,正如我在评论中所说的,一旦你修改了常量值,你就进入了未定义的行为领域,所以谈论正在发生的事情没有多大意义。但他妈的

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

cout这在C++14标准的[dcl.type.cv]/4节中有介绍(早期的标准也有类似的文本):

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


e
是常量对象,
*w=5尝试修改该对象,因此结果是。

您处于未定义的行为区域-任何事情都可能发生。我的大脑太累了,看不到发生了什么,但您可以使用const_cast进行此操作。如果你只是想了解发生了什么,你可以忽略这个评论。@eRender:你可以使用
const\u cast
来解释,但这不会减少行为的不确定性。也许。。。另一种可能性是,编译器注意到“*w=5”,并在第一行中插入了5,而不是*wI-agree。在作用域中初始化的常量int将是编译时常量。这是否意味着将常量变量强制转换为非常量指针是没有用的,因为通过该指针进行修改会导致未定义的行为?基本上,常量的全部要点是不修改值。。。你永远都不应该抛弃常量。我同意尼尔的观点,对于一个较长的解释,
constxc=v
,其中
X
是一个枚举或整数类型,
v
是一个整数常量表达式(即
constintv=5;
)定义了一个常量
c
,它本身可以用作整数常量表达式。这意味着编译器可以在编译
c
的任何用法时内联该值,这是最可能发生的情况。UB是通过
const_cast
(C风格的cast是
const_cast
)修改该常量可能会执行任何操作或根本不执行任何操作,包括终止应用程序。在这种特殊情况下,它正在修改值。