天天看點

内聯函數解讀

1.不能有遞歸

2.不能有靜态資料

3.不能包含循環

4.不能包含switch和goto

5.不能包含數組

這是基本原則,

1)表示這個函數嵌套調用自己,多數情況下是不能内聯的,

但是有時候,是可以優化成跳轉等等情況的,這時候是編譯器是可以内聯的

2)這種時候容易引出錯誤,是以這條是必須遵守的。編譯器很難在内聯的同時,保證語義的正确性。

3)循環有時候,也可以優化成簡單指令序列,此時也是可以内聯的,

但是一般不提倡 寫為内聯函數,而不是編譯器,一定不能内聯

4)switch 多半用位址表,跳轉表等方式實作,内聯通常不能提高效率

goto 是跳轉指令,内聯多半也不能提高效率

5)自動數組初始化,很可能包含循環,這樣也就沒有内聯的必要了

首先,内聯機制被引入C++作為對宏機制的改進和補充(不是取代)。内聯函數的參數傳遞機制與普通函數相同。但是編譯器會在每處調用内聯函數的地方将内聯函數的内容展開。這樣既避免了函數調用的開銷又沒有宏機制的缺陷。

但是程式代碼中的關鍵字”inline”隻是對編譯器的建議:被”inline”修飾的函數不一定被内聯(但是無”inline”修飾的函數一定不是)。這是因為編譯器比絕大多數程式員都更清楚函數調用的開銷有多大,是以如果編譯器認為調用某函數的開銷相對該函數本身的開銷而言微不足道或者不足以為之承擔代碼膨脹的後果則沒必要内聯該函數。(是否會内聯失敗請參考此處)

還有一個原因是為了避免編譯器陷入無窮遞歸。如果内聯函數之間存在遞歸調用則可能導緻編譯器展開内聯函數時陷入無窮遞歸。有時候函數的遞歸調用十分隐蔽,程式員并不容易發現,是以簡單起見,将内聯與否的決定權交給編譯器。

還有一種不被内聯的情況是使用函數指針來調用内聯函數。

(inline)内聯函數不能為虛函數的原因(virtual)

1.内聯函數是個靜态行為,而虛函數是個動态行為,他們之間是有沖突的。

2.我們之是以能看到一些象内聯函數的虛函數,是因為某個函數是否是内聯函數不是由我們說的算,而是由編譯器決定的。我們隻能向編譯器建議,某個函數可以是内聯函數(inline關鍵字),但是編譯器有自己的判斷法則。是以可能出現這樣的情況:

2.1 我們用inline聲明的函數卻沒有inline

2.2 我們沒有用inline聲明的函數卻是inline

2.3 對于inline函數,編譯器仍然将它編譯成一個有位址的函數

是以,情況比較複雜,從high-level來看的話很難判斷函數是否是inline的,如果從low-level來看的話就比較清晰,非内聯函數遵從函數調用機制,在彙編中用call來調用。内聯函數則沒有這些。

繼續閱讀