C++ 对 const 引用参数的依赖没有改变

标签 c++ gcc gcc4.6

请考虑以下代码:

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 在评论中指出,抛弃对象的 constness 并修改它是 UB。引自《笔记》here :

Even though const_cast may remove constness or volatility from any pointer or reference, using the resulting pointer or reference to write to an object that was declared const or to access an object that was declared volatile invokes undefined behavior.

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

相关文章:

c++ - Qt:qobject_cast 的段错误

c++ - FIFO 类型的容器 - 哪种 STL 容器最合适,为什么?

c++ - 将对话框过程作为方法绑定(bind)到自定义类

c++ - 设置加密++

c++ - 关于运算符重载和参数相关查找,Visual Studio 10 和 GCC 4.5 之间的哪个编译器是正确的?

c - 忽略 gobble-only scanf (gcc) 的返回值

c++ - OpenCV 编译问题

c - fscanf 将输出写入变量的索引中

c++ - 编译器错误预期嵌套名称说明符

c++ - 将 void* 与 uint16_t 进行比较