程序的二八法則:“平均而言一個程序的往往將80%的執行時間花在20%的代碼上”——Scott Meyers
目錄
從牛客上一篇帖子談起:
首先明確關於內聯函數的一些概念:
“編譯器隱式的將在類內定義的成員函數當做內聯函數”——《Cpp primer》 223頁中間部分
內聯函數的一些特徵:
- 不包括複雜控制語句,如循環語句等
- 規模很小(一般5句以下)
- 使用頻繁
- 不能遞歸等實現
但是刷OJ的時候,大量的class內部成員函數,如下圖LeetCode爲例,都是inline嗎?
顯然不是!!!很好理解,大部分都不滿足上面提到的inline的幾個特徵。
“內聯函數僅僅是一種請求而沒有強制性”——[STROUSTRUP97] 7.1.1節
但是要完全理解上面這句話還要理解inline調用的過程。
內聯函數調用機制:
- 通過直接將函數體插入調用處來實現
- 函數的每一個調用都以函數本體替換
代碼膨脹:過度熱衷inlining會造成程序提及太大,及時擁有虛內存,inline造成的代碼膨脹會導致額外的換頁行爲,降低指令高速緩存裝置的擊中率,隨之帶來效率損失。
內聯函數的缺點和優點
缺點:
- inline函數無法隨着程序庫的升級而升級
- 無法調試inline函數,因爲怎麼可能在一個不存在的函數體內設置斷點呢?
優點:
前面說了這麼多缺點和注意事項,沒有優點嗎?當然,存在即合理嘛!
- 爲以後的調試和二進制升級帶來便利
- 爲潛在的代碼膨脹問題最小化,是程序的速度提升機會最大化
虛函數、構造函數、析構函數與內聯函數
很顯然,虛函數是不能被優化成內聯函數的
虛函數意味着“等待直到運行是才決定調用哪個函數”
而內聯函數意味着“執行前,先將調用動作替換爲被調用函數的本體”
很明顯相互矛盾!
class中的構造函數,意味着創建一個對象時,每個成員變量都會被自動構造,編譯器會進行大量的異常處理,所以明顯不符合內聯函數小型化的特徵,這個優化建議編譯器肯定不會接受!
參考
- 《Cpp perime plus》
- 《Effective C++》
- 《Essential C++》