內聯函數是定義在類別內部(或加 inline 關鍵字)的函數,其函數體程式碼在編譯期直接展開到呼叫點,消除函數呼叫的棧幀建立、參數傳遞、跳轉返回等開銷。它是零開銷抽象的經典實踐。
C 時代用巨集實現類似功能:
#define ABS(x) ((x) > 0 ? (x) : -(x))
巨集三大禍害:
ABS(++i) 展開為 ((++i) > 0 ? (++i) : -(++i)),i 增加兩次!| 特性 | 巨集 | 內聯函數 |
|---|---|---|
| 展開機制 | 預處理器文字替換 | 編譯器語法樹級展開 |
| 型別檢查 | 無 | 完整(像普通函數) |
| 副作用安全 | 不安全 | 安全(參數求值一次) |
| 作用域 | 全域(無命名空間) | 類別/命名空間作用域 |
| 可存取私有成員 | 否 | 是(類別成員函數) |
| 除錯支援 | 極差 | 良好(保留符號資訊) |
// 顯式 inline
inline int double_val(int x) { return x * 2; }
// 類別內定義 → 隱式 inline
class A {
int read() { return val; } // 自動內聯
void write(int v) { val = v; }
private:
int val;
};
inline 關鍵字只是向編譯器提出請求。編譯器會拒絕內聯當:
&func),需實體地址被拒絕時退化為普通函數呼叫,程式語義完全不變,僅效能差異。
getX()/setX() 等單行資料封裝max、min、swap、數學運算/Ob0 命令列參數或 #pragma auto_inline(off)__attribute__((noinline)) 或 -fno-inline 編譯選項constexpr:C++11 起,constexpr 函數隱含內聯且支援編譯期計算,語意更強。內聯函數是 C++「零開銷抽象」哲學的核心工具。它以編譯器級的語義保證,完美替代了巨集的所有缺陷。但內聯是把雙刃劍:用得好消除呼叫開銷,用得壞導致代碼膨脹、指令快取失效。掌握「小、熱、簡、非虛」四字訣,配合 constexpr 與 PGO,才能發揮最大效能紅利。