Modifying a const through a non-const pointer
I'm a bit confused what happened in the following code:
开发者_开发技巧
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;
In (1), w points to the address of e. In (2), that value was changed to 5. However, when the values of *w and e were displayed, their values are different. But if you print value of w pointer and &e, they have the same value/address.
How come e still contained 2, even if it was changed to 5? Were they stored in a separate location? Or a temporary? But how come the value pointed by w is still the address of e?
As I said in my comment, once you modified the const value you are in undefined behaviour land, so it doesn't make much sense to talk about what is happening. But what the hell..
cout << *w << endl; // (3) outputs 5
cout << e << endl; // (4) outputs 2
At a guess, *w
is being evaluated at runtime, but e
is being treated as a compile time constant
I suspect that you're tripping up the compiler. It doesn't expect you to play dirty tricks with e, so when it sees the line:
cout << e << endl;
It simply inserts the value 2 instead of looking for the actual value. You can verify (or disprove) this by looking at the disassembly of your program.
I'm guessing that the compiler has optimised the value output. It sees that e
is const (so, it can't change -- in theory) and changes cout << e << endl;
to cout << 2 << endl;
. However, e
still has to exist because it's used by w
, so w
correctly takes its address and modifies its value, but you don't see that in the cout
.
Moral of the story -- only declare things const
when you actually want to be const
. Casting away const
ness is not a good idea.
The only thing I can think of is the compiler has some how optimised the code in such a way that any references to e are replaced with a value of 2 even though it assigns memory for e
so in effect (affect?) the line at comment (4) is 'optimized' to be
cout << "2" << endln;
I guess the compiler uses the constness to optimizes out the variable and insert a fixed value into the code.
This is covered by section [dcl.type.cv]/4 of the C++14 standard (earlier standards had similar text too):
Except that any class member declared
mutable
can be modified, any attempt to modify aconst
object during its lifetime results in undefined behavior.
e
is a const object, and *w = 5;
attempts to modify that object, therefore the result is undefined behavior.
精彩评论