2014-01-16 38 views
2

比方說,我在全局命名空間的靜態引用一個靜態對象或原語(或任何其他的命名空間):C++編譯器通常會優化靜態(全局)引用嗎?

int a = 2; 
int& b = a; 

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

    return b; 
} 

這是一個非常簡單的例子,但到底是什麼編譯器通常使用此代碼做?生成的機器代碼是否會實際遍歷一個指針來讀取/寫入a,或者編譯器會插入地址a而不是b

+0

@MarkRansom'b ++','return b'是前面提到的讀/寫操作。 – NmdMystery

+0

@MarkRansom這不是一個指針。 – NmdMystery

+0

如果你的問題是關於一個特定的編譯器,爲什麼不嘗試並找出答案?例如,gcc -S。 – addaon

回答

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完全消失,只是有主要返回常量3,因爲沒有辦法讓另一個編譯單元可以使用這些值。

+0

這很有趣,因爲main是唯一可以訪問a和b的文件。爲什麼'static'在這裏有所作爲? – NmdMystery

+0

@NmdMystery:如果它們不是靜態的,任何其他文件都可以將它們聲明爲'extern'並且可以訪問它們。 –

+0

如果沒有靜態(或匿名命名空間),每個編譯單元(文件)都可以訪問a和b。 – addaon

0

我嘗試disassamble下面的代碼,

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的作爲反彙編器。