Modificar una const a través de un puntero no const

Estoy un poco confundido con lo que sucedió en el siguiente código:

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; 

En (1), w apunta a la dirección de e. En (2), ese valor se cambió a 5. Sin embargo, cuando se muestran los valores de * w y e, sus valores son diferentes. Pero si imprime el valor de w puntero y & e, tienen el mismo valor / dirección.

¿Cómo es que e aún contenía 2, incluso si se cambió a 5? ¿Se almacenaron en una ubicación separada? O un temporal? Pero ¿cómo es que el valor señalado por w sigue siendo la dirección de e?

Como dije en mi comentario, una vez que modifiques el valor de const, estás en un territorio de comportamiento indefinido, por lo que no tiene mucho sentido hablar sobre lo que está sucediendo. Pero qué diablos …

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

En una suposición, *w se está evaluando en tiempo de ejecución, pero e se está tratando como una constante de tiempo de comstackción

Sospecho que estás tropezando con el comstackdor. No espera que juegues trucos sucios con e, así que cuando ve la línea:

 cout << e << endl; 

Simplemente inserta el valor 2 en lugar de buscar el valor real. Puede verificar (o desmentir) esto mirando el desassembly de su progtwig.

Supongo que el comstackdor ha optimizado el valor de salida. Ve que e es const (por lo tanto, no puede cambiar, en teoría) y cambia cout << e << endl; para cout << 2 << endl; . Sin embargo, e todavía tiene que existir porque es utilizado por w , por lo que toma correctamente su dirección y modifica su valor, pero no se ve eso en el cout .

Moraleja de la historia: solo declara cosas const cuando realmente quieres ser const . No es una buena idea deshacerse de la const .

Lo único que se me ocurre es que el comstackdor tiene una forma de optimizar el código de tal manera que cualquier referencia a e se reemplaza con un valor de 2, aunque asigna memoria para e

entonces en efecto (¿afectar?) la línea en el comentario (4) está ‘optimizada’ para ser

 cout << "2" << endln; 

Supongo que el comstackdor usa la constness para optimizar la variable e insertar un valor fijo en el código.

Esto está cubierto por la sección [dcl.type.cv] / 4 del estándar C ++ 14 (los estándares anteriores también tenían un texto similar):

Excepto que cualquier miembro de la clase declarado mutable se puede modificar, cualquier bash de modificar un objeto const durante su vida útil da como resultado un comportamiento indefinido.

e es un objeto const, y *w = 5; intenta modificar ese objeto, por lo tanto, el resultado es un comportamiento indefinido .