引用运算符“&”的结果是什么?关于 const 变量?
有人问我如何更改 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
现在,我不确定 '&x' 返回的确切内容,但它绝对不是 x 的实际地址,因为x 的值没有改变!
但另一方面,ptr did 在开始时包含 x 的值! 那么,它到底是什么?
编辑用VS2010编译
I was asked how can a value of a const variable can be changed.
My my obvious answer was "pointers!" but I tried the next piece of code and I'm puzzled...
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;
}
And the output was:
Value at <some address> :5
Now the value of <same address> is: 6
But the value of x is still 5
Now, I'm not sure exactly what is returned from '&x' but it's definitely not the actual address of x, since the value at x wasn't changed!
But on the over hand, ptr did contain the value of x at the beginning!
So, what is it exactly?
EDIT compiled with VS2010
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您的程序调用未定义的行为(通过指针写入 const 变量是未定义的行为),因此任何事情都可能发生。话虽如此,这里最可能的解释是为什么您会在特定实现中看到这种行为:
当您执行
&x
时,您确实会获得x
的地址。当您执行*ptr = 6
时,您确实将6写入x
的内存位置。但是,当您执行cout << 时x
,您实际上并没有从x
的内存位置读取数据,因为您的编译器通过在此处将x
替换为 5 来优化代码。由于x
是const
,因此编译器可以这样做,因为不存在合法的C++ 程序,这样做会改变程序的行为。Your program invokes undefined behavior (writing to a const variable through a pointer is undefined behavior), so anything might happen. That being said here's the most likely explanation why you get the behavior you see on your particular implementation:
When you do
&x
, you do get the address ofx
. When you do*ptr = 6
, you do write 6 tox
's memory location. However when you docout << x
, you don't actually read fromx
's memory location because your compiler optimized the code by replacingx
with 5 here. Sincex
isconst
the compiler is allowed to do that since there is no legal C++ program in which doing so would change the program's behavior.编译器将
x
缓存在寄存器中,因此内存中的值发生了变化,但最后的打印输出仍然是相同的。查看生成的程序集(使用-s
进行编译)。Compiler caches
x
in a register, so the value in memory changes, but the last print-out is still the same. Check out generated assembly (compile with-s
).首先,这种行为是未定义的。也就是说,可能会发生以下情况:
当您执行此操作时:
5
存储在某处的某个地址。这就是指针似乎工作正常的原因。 (尽管抛弃 const 仍然是未定义的行为)但是,由于编译器优化,
x = 5
只是作为最终打印语句中的文字内联。编译器认为它是安全的,因为x
被声明为const
。这就是为什么你打印出原始值 5。
First of all, this behavior is undefined. That said, here's what's probably going on:
When you do this:
The
5
is stored at some address at somewhere. That's why the pointer seems to work properly. (although casting away the const is still undefined behavior)However, due to compiler optimizations
x = 5
is just inlined as a literal in the final print statement. The compiler thinks it's safe becausex
is declaredconst
.That's why you print out the original value 5.
也许您遇到了代码优化的副作用,请尝试通过禁用所有优化来运行相同的代码,或者检查 asm 生成的代码。我猜编译器正在重用函数中某个注册表中的值,因为他押注于 const,所以即使您实际上正在更改该值,更改后的值也不会正确传播。正如基思在评论中注意到的那样,原因是你正在玩一种未定义的行为。
Maybe you are experiencing a side effect of code optimization, try to run the same code by disabling all optimization, or check at the asm generated code. I guess the compiler is reusing the value it has in some registry along the function since he bet on the const, so even if you are actually changing the value, the changed value is not propagated properly. The reasons for that as Keith noticed in the comemnts, is that you are palying with an undefined behavior.
&x
返回的是一个指向 const int 的指针(即int const*
)。现在,指针实际上被实现为保存地址,但指针不是地址,您的示例很好地说明了原因:即使在运行时不存在,指针的类型仍然起着重要作用。在您的情况下,您正在抛弃 const,从而对编译器撒谎“此指针指向非 const int”。然而,编译器从声明中知道
x
的值不能改变(它被声明为 const),并自由地使用这个事实(并且标准允许这样做:您尝试通过指针更改它)转换为非 const int 是未定义的行为,因此允许编译器执行任何操作)。What is returned from
&x
is a pointer to const int (i.e.int const*
). Now pointers are inded implemented as holding the address, but pointers are not addresses, and your example shows quite nicely why: The type of the pointer, even though not present at run time, still plays an important role.In your case, you are casting away the const, and thus lying to the compiler "this pointer points to a non-const int". However the compiler knows from the declaration that the value of
x
cannot change (it was declared const), and makes freely use of that fact (and the standard allows it: Your attempt to change it through a pointer to non-const int is undefined behaviour and therefore the compiler is allowed to do anything).