有人问我怎样才能改变const变量的值。
我明显的回答是"指针!"但我尝试了下一段代码,我感到困惑......
int main()
{
const int x = 5;
int *ptr = (int *)(&x); // "Cast away" the const-ness..
cout << "Value at " << ptr << ":"<< (*ptr) <<endl;
*ptr = 6;
cout << "Now the value of "<< ptr << " is: " << (*ptr) <<endl;
cout << "But the value of x is still " << x <<endl;
return 0;
}
输出结果为:
Value at <some address> :5
Now the value of <same address> is: 6
But the value of x is still 5
现在,我不确定&#39;&amp; x&#39;但它绝对不是x的实际地址,因为x的值没有改变!
但总的来说,ptr 确实包含x的值! 那么,到底是什么?
使用VS2010编译编辑
答案 0 :(得分:15)
您的程序调用未定义的行为(通过指针写入const变量是未定义的行为),因此可能发生任何事情。这就是说,为什么你得到你在特定实现上看到的行为最可能的解释:
执行&x
后,您的确会获得x
的地址。执行*ptr = 6
时,您会在x
的内存位置写入6。但是当你执行cout << x
时,实际上并没有从x
的内存位置读取,因为编译器通过将x
替换为5来优化代码。由于x
是const
,因此编译器可以这样做,因为没有合法的C ++程序会这样做会改变程序的行为。
答案 1 :(得分:2)
编译器在寄存器中缓存x
,因此内存中的值会发生变化,但最后一次打印输出仍然相同。检查生成的程序集(使用-s
编译)。
答案 2 :(得分:2)
首先,此行为未定义。也就是说,这是可能发生的事情:
执行此操作时:
int *ptr = (int *)(&x);
5
存储在某处的某个地址。这就是指针似乎正常工作的原因。 (虽然抛弃const仍然是未定义的行为)
但是,由于编译器优化x = 5
在最终的print语句中只是作为文字内联。编译器认为它是安全的,因为x
被声明为const
。
cout << "But the value of x is still " << x <<endl;
这就是你打印原始值5的原因。
答案 3 :(得分:1)
也许您遇到代码优化的副作用,尝试通过禁用所有优化来运行相同的代码,或检查asm生成的代码。我猜编译器正在重复使用它在函数的某个注册表中的值,因为他打赌const,所以即使你实际上在改变值,改变的值也不会正确传播。 Keith在游戏中注意到的原因是你正在采取不明确的行为。
答案 4 :(得分:0)
从&x
返回的是指向const int的指针(即int const*
)。现在指针被实现为保存地址,但指针 不是地址,你的例子显示了很好的原因:指针的类型,即使在运行时不存在,仍然起着重要的作用
在你的情况下,你正在抛弃const,因此向编译器说谎“这个指针指向一个非const int”。然而,编译器从声明中知道x
的值不能改变(它被声明为const),并且可以自由地使用这个事实(并且标准允许它:你试图通过非指针来改变它) const int是未定义的行为,因此允许编译器执行任何操作。