So, aside from the "it's undefined behaviour" (which it is), the compiler is perfectly fine to use the fact that M
is a constant, thus won't change, in the evaluation of cout ... << M << ...
, so can use an instruction that has the immediate value 10, instead of the actual value stored in the memory of M
. (Of course, the standard will not say how this works, more than "it's undefined", and compilers are able to choose different solutions in different circumstances, etc, etc, so it's entirely possible that you'll get different results if you modify the code, use a different compiler, different version of compiler or the wind is blowing in a different direction).
Part of the tricky bit with "undefined behaviour" is that it includes things that are "perfectly what you may expect" as well as "nearly what you'd expect". The compiler could also decide to start tetris if it discovers this is what you are doing.
And yes, this is very much one of the reasons why you SHOULD NOT use const_cast
. At the very least NOT on things that were originally const
- it's OK if you have something along these lines:
int x;
void func(const int* p)
{
...
int *q = const_cast<int *>(p);
*q = 7;
}
...
func(&x);
In this case, x
is not actually const, it just becomes const when we pass it to func
. Of course, the compiler may still assume that x
is not changed in func
, and thus you could have problems....