[请注意,我通过引用定义了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;
时,可以在调用位置在编译时处将k
替换为1
,因此无论您做什么,您实际上都在执行cout << *pk << ' ' << 1;
到k
在运行时。但是,由于k
是您要获取其地址的编译时常量,因此必须将其存储在内存中,并且编译器可以自由(并且很可能)将该值存储在只读内存中。在运行时更改此类内存可能会使您的应用程序崩溃,但这不是guarantee。