C ++编译器通常会优化静态(全局)引用吗?

时间:2014-01-16 03:17:33

标签: c++ reference compiler-optimization

假设我对全局命名空间(或任何其他命名空间)中的静态对象或基元有静态引用:

int a = 2;
int& b = a;

int main(int argc, char** argv) {
    b++;

    return b;
}

这是一个非常基本的例子,但编译器通常使用这段代码做什么?生成的机器代码是否实际遍历读/写a的指针,或者编译器是否只插入a的地址代替b

2 个答案:

答案 0 :(得分:2)

对此的答案显然是编译器特定的。我决定尝试使用x86-64上的clang-500.2.79和-O3标志。如上所述,您的来源产生:

    .section    __TEXT,__text,regular,pure_instructions
    .globl  _main
    .align  4, 0x90
_main:                                  ## @main
    .cfi_startproc
## BB#0:
    pushq   %rbp
Ltmp2:
    .cfi_def_cfa_offset 16
Ltmp3:
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
 Ltmp4:
    .cfi_def_cfa_register %rbp
    movl    _a(%rip), %eax
    incl    %eax
    movl    %eax, _a(%rip)
    popq    %rbp
    ret
    .cfi_endproc

    .section    __DATA,__data
    .globl  _a                      ## @a
    .align  2
_a:
    .long   2                       ## 0x2

    .section    __DATA,__const
    .globl  _b                      ## @b
    .align  3
_b:
    .quad   _a

正如您所看到的,ab符号都被保留(分为_a_b);这是必需的,因为这些符号具有全局联系。

如果您稍微更改代码,要将ab声明为静态,结果会大不相同:

    .section    __TEXT,__text,regular,pure_instructions
    .globl  _main
    .align  4, 0x90
_main:                                  ## @main
    .cfi_startproc
## BB#0:
    pushq   %rbp
Ltmp2:
    .cfi_def_cfa_offset 16
Ltmp3:
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
Ltmp4:
    .cfi_def_cfa_register %rbp
    movl    $3, %eax
    popq    %rbp
    ret
    .cfi_endproc

在这种情况下,编译器能够完全优化ab,并且只需要main返回常量3,因为其他编译单元无法使用这些值。< / p>

答案 1 :(得分:0)

我试图取消代码,

int pranit = 2;
int& sumit = pranit;

int main(int argc, char** argv) {
    sumit++;

    return sumit;
}

以下说明建议pranit有sumit的地址。

013B13C8    8B15 04803B01   MOV EDX,DWORD PTR [sumit]                ; ConsoleA.pranit

此外,两个变量都有不同的地址,

Names in ConsoleA, item 313
 Address=013B8004
 Section=.data
 Type=Library
 Name=sumit

Names in ConsoleA, item 257
 Address=013B8000
 Section=.data
 Type=Library
 Name=pranit

我使用OllyDbg作为反汇编程序。

相关问题