inline
inline是C++提供的一個關鍵字,它用於函數定義之前,表示把函數定義為內聯函數。內聯函數的含義是:在函數調用點把函數體直接展開,取代函數調用。
inline int getZero() {
return 0;
}
int a = getZero();
如果上述函數沒有定義為inline,那么在聲明a時,程序實際上的工作是,把getZero()函數壓入棧中,執行函數得到返回值0並出棧,最后把0賦值給a。在定義為inline之后,編譯器會把作為內聯函數的函數體在調用點,也就是在聲明a時展開,直接得到結果0並賦值給a,省去了函數入棧和出棧的調用過程,提升了性能。
那么如果是復雜一點的內聯函數呢?
inline int get(int a, int b, int c, int x) {
return (a * x + b) * x +c;
}
int b = get(1, 2, 1, 4);
比起之前的getZero(),get()函數多了許多運算,它在調用點也會被展開為int b = (1 * 4 + 2) * 4 + 1;。可想而知,越復雜的函數體內聯展開越困難。
由此也引出了內聯函數定義的特點:
inline關鍵字對編譯器起建議作用,是否內聯編譯由編譯器決定。inline關鍵字出現在函數聲明處不起作用,出現在函數定義時有效。- 把邏輯復雜的函數定義為內聯是無意義的,如嵌套調用、遞歸等。
- 類內定義的函數都是隱式內聯的,類外定義需要顯式加上
inline關鍵字。
// inline無意義
inline int f1(int x) {
if (x == 0 || x== 1) return 1;
return f(x - 1) + f(x - 2);
}
// inline無意義
inline int f2();
class LiF {
public:
LiF() = default;
LiF(int _lif);
void set(int _lif) { lif = _lif; } // 類內隱式內聯
int get();
private:
int lif;
}
LiF::LiF(int _lif): lif(_lif) {} // 無內聯
inline int LiF::get() { return lif; } // 類外顯式內聯
既然內聯可以提高效率,那為什么不把所有函數都定義為內聯呢?這個問題也不難解答。內聯的前提是可以在調用點展開,顯然之前提到的復雜函數時無法展開的;而如果某次內聯函數執行消耗的時間遠長於調用的消耗,那么這次內聯也是失敗的。再者,程序效率提升的背后必然有更大的內存消耗,內聯帶來的效率提升是通過復制代碼到調用點實現的,這顯然就增加了代碼量。那么這就要求程序員謹慎地使用inline。
