C++依赖于const引用的参数不会改变

Sha*_*esh 8 c++ gcc gcc4.6

请考虑以下代码:

void func1(const int &i);
void func2(int i);

void f()
{
  int a=12;
  func1(a);
  func2(a);
}
Run Code Online (Sandbox Code Playgroud)

用g ++ 4.6和-O3编译,我可以看到编译后重新读取函数调用之间的"a"值.将a的定义更改为"const int",编译器不会这样做,而是简单地将立即值"12"加载到edi中.如果a不是const,则同样如此,但我将func1的签名更改为按值接受.

虽然不是代码生成中的错误,但这仍然是奇怪的行为.因为func1承诺不改变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                                                           
Run Code Online (Sandbox Code Playgroud)

将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
Run Code Online (Sandbox Code Playgroud)

Pra*_*han 6

在C++中,const实际上只是逻辑const而不是物理const.func1可以做一个const_cast并修改i.const就像枪的安全 - 你仍然可以用脚射击自己,但不是偶然的.

正如TC和juanchopanza在评论中指出的那样,抛弃const一个物体并修改它是UB.引用"注释" 在这里:

尽管const_cast可以从任何指针或引用中删除constness或volatile,但是使用结果指针或引用来写入声明为const的对象或访问声明为volatile的对象会调用undefined行为.