请考虑以下代码:

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并修改iconst就像枪支的安全性一样-您仍然可以用脚射击自己,但并非偶然。

作为T.C. Juanchopanza和Juanchopanza在评论中指出,丢弃对象的const并修改它为UB。引用“Notes” here:

关于C++对const引用参数的依赖没有改变,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25029516/

10-11 22:42
查看更多