inline 本質:編譯器建議而非命令
inline 只是請求編譯器將函數體嵌入調用點。編譯器可拒絕(如函數過大、含循環/遞歸、虛函數)。隱式 inline:類內定義成員函數;顯式 inline:關鍵字修飾。
優點:消除函數調用開銷 + 上下文優化
- 無壓棧/彈棧、跳轉指令。
- 編譯器可基於調用點上下文進行常量傳播、死代碼消除、循環展開等深度優化。
- 若函數體極小(比調用序列更小),反而減小代碼體積、提高指令緩存命中率。
缺點:代碼膨脹風險
- 多處調用導致函數體多份複製,增加二進制體積。
- 可能導致指令緩存 miss、頁錯誤,反而降低性能。
- 調試困難:無獨立棧幀、斷點設置受限、變量觀察不便。
不宜 inline 的典型場景
| 場景 | 原因 |
| 構造/析構函數 | 隱含基類/成員調用、異常處理代碼,實際體積龐大 |
| 虛函數 | 運行時動態綁定,無法編譯期內聯 |
| 函數指針調用 | pf() 通過指針調用無法內聯 |
| 庫接口函數 | 內聯變更需重新編譯客戶代碼,破壞二進制兼容 |
決策原則
- 預設不 inline:只有明證收益(極小、高頻、非虛、非庫接口)才加。
- 遵循 80/20 原則:20% 熱點代碼決定 80% 性能,剖析後再針對性內聯。
- 模板不自動意味 inline:模板定義在頭文件是為了實例化,非為內聯。需額外加
inline 關鍵字。
最佳實踐清單
- 存取器
int age() const { return _age; } → 適合隱式 inline。
- 複雜算法、IO、加鎖操作 → 絕不 inline。
- 庫開發者:接口函數謹慎 inline,保持 ABI 穩定。