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
)修改该常量可能会执行任何操作或根本不执行任何操作,包括终止应用程序。在这种特殊情况下,它正在修改值。