您正在使用有问题的代码调用未定义的行为,试图更改声明为的变量,方法const
是丢弃 const 是不允许的(除非const 变量实际上是对不是的变量的引用const
)。
对您的结果的一种合理且极有可能的解释是,编译器知道 的值不a
应该改变,因此它几乎可以替换所有出现的a
with 5
。IE。“查找”已优化。
当它被声明为 always be 时,为什么要查看它的地址a
来读取它的值5
?
让我们看看编译器可能会将代码片段转换成哪些指令
foo.cpp
void func (int)
{
/* ... */
}
int
main (int argc, char *argv[])
{
const int a = 10;
int * p = &const_cast<int&> (a);
*p = 20;
func (a);
}
main
如给出的组装说明g++ -S foo.cpp
main:
.LFB1:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $32, %rsp
movl %edi, -20(%rbp)
movq %rsi, -32(%rbp)
movl $10, -12(%rbp)
leaq -12(%rbp), %rax
movq %rax, -8(%rbp)
movq -8(%rbp), %rax # store the adress of `a` in %rax
movl $20, (%rax) # store 20 at the location pointed to by %rax (ie. &a)
movl $10, %edi # put 10 in register %edi (placeholder for first argument to function)
# # notice how the value is not read from `a`
# # but is a constant
call _Z4funci # call `func`
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
如上所见, 的值20
确实放置在包含 ( ) 的地址的存储%rax
地址(%rax)
中a
,movl $20, (%rax)
但我们调用的参数void func (int)
是常数10
( movl $10, %edi
)。
如前所述;编译器假定 的值a
不会改变,而不是每次a
使用时都读取内存位置,而是将其替换为常量 value 10
。