请考虑以下代码:
void func1(const int &i);
void func2(int i);
void f()
{
int a=12;
func1(a);
func2(a);
}
在带有-O3的g++ 4.6中,我可以看到编译器在函数调用之间重新读取了“a”的值。将a的定义更改为“const int”时,编译器不会执行此操作,而是仅将立即值“12”加载到edi中。如果a不是const,也是如此,但是我将func1的签名更改为按值接受。
尽管这不是代码生成中的错误,但这仍然是奇怪的行为。既然func1 promise 不更改a,为什么编译器的代码应该基于a是否为const进行更改?
编辑:一些怀疑论者声称我可能读错了代码。上面的代码通过-S编译产生以下结果:
_Z1fv:
.LFB0:
.cfi_startproc
subq $24, %rsp
.cfi_def_cfa_offset 32
leaq 12(%rsp), %rdi
movl $12, 12(%rsp)
call _Z5func1RKi
movl 12(%rsp), %edi <-- Rereading a
call _Z5func2i
addq $24, %rsp
.cfi_def_cfa_offset 8
ret
.cfi_endproc
将a更改为const会产生:
_Z1fv:
.LFB0:
.cfi_startproc
subq $24, %rsp
.cfi_def_cfa_offset 32
leaq 12(%rsp), %rdi
movl $12, 12(%rsp)
call _Z5func1RKi
movl $12, %edi <-- Use immediate value
call _Z5func2i
addq $24, %rsp
.cfi_def_cfa_offset 8
ret
.cfi_endproc
最佳答案
在C++中,const
实际上只是逻辑常量,而不是物理常量。 func1
可以执行const_cast
并修改i
。 const
就像枪支的安全性一样-您仍然可以用脚射击自己,但并非偶然。
作为T.C. Juanchopanza和Juanchopanza在评论中指出,丢弃对象的const
并修改它为UB。引用“Notes” here:
关于C++对const引用参数的依赖没有改变,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25029516/