比方說,我在全局命名空間的靜態引用一個靜態對象或原語(或任何其他的命名空間):C++編譯器通常會優化靜態(全局)引用嗎?
int a = 2;
int& b = a;
int main(int argc, char** argv) {
b++;
return b;
}
這是一個非常簡單的例子,但到底是什麼編譯器通常使用此代碼做?生成的機器代碼是否會實際遍歷一個指針來讀取/寫入a
,或者編譯器會插入地址a
而不是b
?
比方說,我在全局命名空間的靜態引用一個靜態對象或原語(或任何其他的命名空間):C++編譯器通常會優化靜態(全局)引用嗎?
int a = 2;
int& b = a;
int main(int argc, char** argv) {
b++;
return b;
}
這是一個非常簡單的例子,但到底是什麼編譯器通常使用此代碼做?生成的機器代碼是否會實際遍歷一個指針來讀取/寫入a
,或者編譯器會插入地址a
而不是b
?
對此的回答顯然是編譯器特定的。我決定嘗試在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
正如你可以看到,這兩個符號a
和b
保留(被改寫的,以_a
和_b
);這是必需的,因爲這些符號具有全球聯繫。
如果你改變你的代碼略有下降,申報a
和b
爲靜態的,其結果是完全不同的:
.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
在這種情況下,編譯器能夠優化a
和b
完全消失,只是有主要返回常量3,因爲沒有辦法讓另一個編譯單元可以使用這些值。
這很有趣,因爲main是唯一可以訪問a和b的文件。爲什麼'static'在這裏有所作爲? – NmdMystery
@NmdMystery:如果它們不是靜態的,任何其他文件都可以將它們聲明爲'extern'並且可以訪問它們。 –
如果沒有靜態(或匿名命名空間),每個編譯單元(文件)都可以訪問a和b。 – addaon
我嘗試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的作爲反彙編器。
@MarkRansom'b ++','return b'是前面提到的讀/寫操作。 – NmdMystery
@MarkRansom這不是一個指針。 – NmdMystery
如果你的問題是關於一個特定的編譯器,爲什麼不嘗試並找出答案?例如,gcc -S。 – addaon