說我有一些功能,每個代碼大約兩個簡單的線條,和他們互相稱呼這樣的:A
電話B
電話C
調用D
...調用K
。 (所以基本上這是一系列短的函數調用。)編譯器通常會在調用樹中嵌入這些函數多深?編譯器內聯函數有多深?
回答
的問題是沒有意義的。
如果你仔細想想內聯,而其後果,你就會意識到這一點:
- 避免了函數調用(與所有的寄存器保存/幀調整)
- 自曝更多背景信息優化(死了商店,死碼,公共子表達式elimintation ...)
- 重複碼(腹脹指令緩存和可執行文件的大小,除其他事項外)
決定當無論是否內聯,編譯器都會在潛在的膨脹和預期的速度增益之間執行平衡操作。這種平衡行爲受到選項的影響:對於gcc -O3
意味着優化速度,而-Oz
意味着對尺寸進行優化,在內聯時它們具有準相反的行爲!
因此,重要的不是「嵌套層次」是指令的數量(可能加權因爲不是所有的都是一樣的)。
這意味着,一個簡單的轉發功能:
int foo(int a, int b) { return foo(a, b, 3); }
是從視點內聯基本上是「透明的」。
另一方面,計算一百行代碼的函數不太可能被內聯。除了一次只調用一次的自由函數是準系統內聯的,因爲它在這種情況下不會造成任何重複。
從這兩個例子,我們得到的啓發是如何表現一種預感:
- 少的指令功能有,用於inling
- 的次數越少就越好叫法,內聯 更好
在那之後,他們的參數,你應該能夠設置影響這種或那種方式(MSVC爲__force_inline
強烈的inling暗示,gcc
因爲他們-finline-limit
標誌,以「提高」的tresh舊的指令數等...)
在切線:你知道部分內聯?
它是在4.6中的gcc中引入的。顧名思義,這個想法是部分內聯一個功能。大多數情況下,爲了避免函數被「守護」時函數調用的開銷,並且可能(在某些情況下)幾乎立即返回。
例如:
void foo(Bar* x) {
if (not x) { return; } // null pointer, pfff!
// ... BIG BLOC OF STATEMENTS ...
}
void bar(Bar* x) {
// DO 1
foo(x);
// DO 2
}
可以得到 「優化」 爲:
void [email protected](Bar* x) {
// ... BIG BLOC OF STATEMENTS ...
}
void bar(Bar* x) {
// DO 1
if (x) { [email protected](x); }
// DO 2
}
當然,再次爲內聯啓發式申請,但他們更多的申請有差別!
最後,除非你使用WPO(全程序優化)或LTO(鏈接時間優化)功能只能如果他們的定義是相同的TU(翻譯單元)內聯該調用點。
我通常不會這樣做,但我認爲我應該改變接受的答案。 :)我不知道部分內聯,也不知道基於調用次數的內聯。感謝細節。 –
我見過編譯器內聯多於5個函數。但在某種程度上,它基本上成爲編譯器所做的空間效率權衡。每個編譯器在這方面都有所不同。 Visual Studio對於內聯非常保守。 GCC(-O3下)和英特爾編譯愛內聯......
- 1. C/C++編譯器可以內聯malloc()內聯函數嗎?
- 2. 當內聯函數的編譯過程
- 3. 內聯函數代碼不能編譯
- 4. 爲什麼Delphi編譯器不內聯彙編函數?
- 5. 是否有內聯網頁編譯器?
- 6. C51 C編譯器內聯彙編到SDCC內聯彙編
- 7. 靜態模板函數可以通過編譯器內聯嗎?
- 8. 編譯器是否決定何時內聯函數(使用C++)?
- 9. 編譯器如何處理內聯導出函數?
- 10. 谷歌封閉編譯器 - 不內聯goog lib函數調用?
- 11. 編譯器如何管理返回內聯函數?
- 12. 編譯器是否會在沒有主體的情況下內聯函數?
- 13. 編譯器內聯比內聯手動更好嗎?
- 14. ç內聯彙編幫助(數字火星C編譯器)
- 15. VB.NET或C#中的內聯函數和條件編譯?
- 16. 與模板內聯函數編譯錯誤
- 17. 在使用-O3編譯時將函數標記爲內聯?
- 18. 修改內聯樣式,多元素深
- 19. 檢查一個特定函數是否內聯英特爾編譯器
- 20. 爲什麼不將編譯器內聯函數寫入不同的源文件?
- 21. 編譯器會忽略我的函數的內聯限定符嗎?
- 22. 爲什麼編譯器堅持我的函數是內聯的呢?
- 23. Can/do C編譯器能夠優化內聯函數的地址嗎?
- 24. 編譯器如何決定是否值得讓我的函數內聯?
- 25. 現在的C++編譯器內聯函數只能調用一次嗎?
- 26. Linux內核2.4.32編譯中多種函數的多重定義
- 27. Java編譯器是否有效地處理內聯字符串?
- 28. 使用SSE2內在函數和gcc內聯彙編器
- 29. 將編譯器與編輯器關聯
- 30. 內聯函數
您可以簡單地測試並查看程序集!您的編譯器文檔應該告訴您如何指定內聯深度;我認爲默認情況下GCC的值大概是50。 –
我相信這應該是編譯器特定的,並且不會發布編譯器的信息。 –
在MSVC下,您可以使用'#pragma inline_depth'(http://msdn.microsoft.com/zh-cn/library/cx053bca.aspx)對此進行部分控制,儘管在某些情況下我遇到了問題(例如遞歸內聯,這是有可能的,但從來沒有工作,最終做手工) – Necrolis