Item 30 理解 inline 函式的裡裡外外

2022-05-28 04:33:11 字數 1084 閱讀 8974

內聯函式的好處太多了:

但 inline 函式也並非免費的午餐:

inline 只是對編譯器的乙個請求而非命令。該請求可以隱式地進行也可以顯式地宣告。

當你的函式較複雜(比如有迴圈、遞迴),或者是虛函式時,編譯器很可能會拒絕把它 inline。因為虛函式呼叫只有執行時才能決定呼叫哪個,而 inline 是在編譯器便要嵌入函式體。 有些編譯器在 dianotics 級別編譯時,會對拒絕 inline 給出 warning 。

隱式的辦法便是把函式定義放在類的定義中:

class person  // 這會生成乙個inline函式!

};

例子中是成員函式,如果是友元函式也是一樣的。除非友元函式定義在類的外面。

顯式的宣告則是使用 inline 限定符:

templateinline const t& max(const t& a, const t& b)

void (*pf)() = f;

f(); // 這個呼叫將會被inline,它是個普通的函式呼叫

pf(); // 這個是通過指標呼叫的,不會被inline

構造析構函式看起來很適合 inline,但事實並非如此。我們知道c++會在物件建立和銷毀時保證做很多事情,比如呼叫new時會導致建構函式被呼叫, 退出作用域時析構函式被呼叫,構造函式呼叫前成員物件的建構函式被呼叫,構造失敗後成員物件被析構等等。

這些事情不是平白無故發生的,編譯器會生成一些**並在編譯時插入你的程式。比如編譯後乙個類的構造過程可能是這樣的:

derived::derived()

catch(...)

trycatch(...)

...}

derived 的析構函式、base 的構造和析構函式也是一樣的,事實上構造和析構函式會被大量地呼叫。 如果全部inline 的話,這些呼叫都會被擴充套件為函式體,勢必會造成目標**膨脹。

如果你是庫的設計者,那麼你的介面函式的 inline 特性的變化將會導致客戶**的重新編譯。 因為如果你的介面是 inline 的,那麼客戶需要將函式體展開編譯到客戶的目標**中。

小問題大思考之C 裡的inline函式

inline,乙個神奇的關鍵字。有了它,你同時就可以獲取函式和巨集的優點。inline定義的函式,比起沒有inline的函式來說,沒有執行函式呼叫所帶來的負擔 對此可參見 c 程式的記憶體布局 因此它是高效率的 比起巨集來,它具有函式的可預期行為和引數型別檢驗。巨集的行為難於預期,我們看看下面這個巨...

js函式柯里化的理解

函式柯里化理解示例 求和 let add function a,b,c else 引數解構版本 function curry fn,args let f1 add.bind console.log f1 2,3 5 但是簡單版bind實現不支援物件和其他引數同時傳入,如下 let f2 add.bi...

scala 函式柯里化的理解

使用函式柯里化的好處一 簡化巢狀函式的開發 沒有使用柯里化的時候,是兩個函式巢狀使用 def test2 fun 呼叫 test2 結果 xx 使用了函式柯里化 使用了兩個引數列表 兩個引數列表,就不必再使用巢狀函式了,而且和test2 實現的結果一樣。達到了簡化巢狀函式的效果 def test3 ...