8

Please consider the following code:

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

void f()
{
  int a=12;
  func1(a);
  func2(a);
}

Compiled with g++ 4.6 with -O3, I can see that the compiled re-reads the value of "a" between the function calls. Changing a's definition to "const int", the compiler doesn't do that, and instead simply loads immediate value "12" into edi. The same is true if a is not const, but I change func1's signature to accept by value.

While not a bug in the code generation, this is still weird behavior. Being as it is that func1 made a commitment not to change a, why should the compiler's code change based on whether a is const or not?

Edit: Some skeptics claim that I might be reading the code wrong. The above code produces the following with -S compilation:

_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                                                           

Changing a to const produces:

_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
4

2 回答 2

6

在 C++ 中,const实际上只是逻辑常量而不是物理常量。func1可以做一个const_cast和修改iconst就像一把枪的安全性——你仍然可以射中自己的脚,但不是偶然的。

正如 TC 和 juanchopanza 在评论中指出的那样,抛弃const对象的本质并对其进行修改是 UB。在此处引用“注释” :

即使 const_cast 可以从任何指针或引用中删除 const 或易失性,使用生成的指针或引用来写入声明为 const 的对象或访问声明为 volatile 的对象会调用未定义的行为。

于 2014-07-30T05:45:35.627 回答
3

总结答案,我认为这最好地解释了它:

对非 const 变量进行 const 引用是合法的,然后丢弃 const 性。因此,第一种情况下的编译器不能假设 func1 不会改变a

如果将 const 转换为声明为 const 的变量会发生什么是未定义的。第二种情况下的编译器可能会假设 func1 不会抛弃常量。如果 func1 确实抛弃了常量, func2 将收到“错误”的值,但这只是未定义行为的一个后果。

于 2014-07-30T08:17:54.057 回答