请参阅,我通过引用定义了const int & a = 1
,并强制指针将pa
转换为a
,并通过更改pa
来更改a的值。这是成功的。
但是,当定义了const int k = 1
并且重复上述操作时,尽管pk
和k
是相同的地址,但是* pk
和k
不是相同的值。
它背后的原理是什么?
当我这样做的时候,你能解释一下IDE是如何处理内存分配的吗?
const int &a = 1;
int *pa = (int*)&a;
cout << &a << endl;
cout << pa << endl;
*pa = 2;
cout << a << endl;
//And here is the outcome.
//0x7ffeeb5d8a24
//0x7ffeeb5d8a24
//2
因此,我们成功地更改了a
。
const int k = 1;
cout << &k << endl;
int *pk = (int*)&k;
cout << &k << endl;
cout << pk << endl;
*pk = 2;
cout << *pk << ' ' << k;
//0x7ffeeb5d8a14
//0x7ffeeb5d8a14
//0x7ffeeb5d8a14
//2 1
//Process finished with exit code 0
这里的*pk
和k
地址相同,但值不相同!这怎么会发生?
这在技术上是未定义的行为。在运行时修改const
数据是不安全的,即使去掉了它的常量也是如此。只有最初不是const
并且后来添加了const
的数据才能安全地丢弃该const
。
但是,为了解释为什么您看到的输出让您感到困惑,答案是编译器优化!
编译器将const int k = 1;
视为编译时间常数,并假定k
永远不会更改值(这是正确的!(。当编译器看到cout << *pk << ' ' << k;
时,允许在编译时在调用站点用值1
替换k
,因此无论在运行时对k
做了什么,您实际上都在执行cout << *pk << ' ' << 1;
。但是,由于k
是一个编译时常数,您可以获取它的地址,它必须存储在内存中,编译器可以自由地(很可能会(将该值存储在只读内存中。在运行时更改这样的内存可能会使您的应用程序崩溃,但这并不能保证。