2013-12-09 35 views
0

據我所知,g++與優化開啓後就會刪除函數調用bar完全有如下情況:g ++空函數刪除是否遞歸地工作?

int bar() { }  
int foo() { bar(); } 

然而,考慮以下兩種情況下,被定義爲上述bar

情況1:

int foo(int a, int b) { 
    if (a > b) bar(); 
} 

情況2:

int foo() { bar(); } 
int foo2() {foo(); } 

在情況1中,if語句也會被刪除,因爲即使條件爲真,它也會執行死代碼?

在情況2中,將內的foo的呼叫移除?

+0

看看反彙編。這並不難看出。 –

+3

你知道你可以試試看嗎?例如,使用GCC的-S選項來編譯但不能組裝,那麼你將能夠很容易地讀取它正在做的事情。 –

+0

@JohnZwinck,我會試試。我原本對disas猶豫不決,因爲我不確定要尋找什麼,因爲我猜想編譯器會內聯。 – merlin2011

回答

0

編譯器不會刪除整個函數,鏈接器會這樣做。

如果您正在構建可執行文件(或者函數未從庫中導出),則鏈接程序將刪除所有的孤立函數。如果沒有,這是一個錯誤:)。保存函數的地址(例如,在一個變量中或將它傳遞給另一個函數)保證該函數將保持不變。

編輯 只是,要清楚的是,優化編譯器將內聯函數,有效地消除它認爲必要的函數調用。在上面的例子中(超級簡單的函數),毫無疑問,它會嵌入它們。順便說一句,STL的實現(和提升)很大程度上依賴於這個特性。

+2

這不是關於刪除*函數*,而是關於刪除*調用*。 –

+0

除非禁用此功能,否則編譯器將簡化函數內聯,刪除調用。我會更新答案 – egur

1

繼在意見的建議,我該試着自己,似乎空函數調用確實在我所描述的,至少對於gcc 4.8.1g++ 4.8.1這兩種情況下遞歸完全去除。

我編譯了以下兩個程序,首先用gcc -S,然後用gcc -S -O2

計劃1:

int bar() { } 
int foo() { bar(); } 
int main() { 
    foo(); 
} 

方案2:

int bar() { } 

int foo(int a, int b) { 
    if (a > b) bar(); 
} 

int main() { 
    foo(2,1); 
} 

我也foo的參數從命令行傳遞進來,試圖以確保拆除是因爲通過常量不到foo

int main(int argc, char** argv) { 
    foo(argc,1); 
}