2015-01-12 62 views
1

從我所知道的內聯函數是一個優化來提高性能,因此它應該像宏一樣快速運行。內聯函數的代碼應儘可能短。定義一個調用其他函數的內聯函數是否有意義?

我不知道是否有必要在內聯函數中嵌入函數調用。如果答案是肯定的,那麼在哪種情況下還有什麼限制?

其實我問這個問題是因爲我查看了一個從內聯函數調用諸如「socket()」,「sendto()」和「memset()」等函數的代碼;在我看來,這會超越內聯函數的目的。

注意:在代碼中,我沒有使用對函數的任何條件調用,內聯函數只是將參數傳遞給被調用的函數。

+0

內聯工作過一個建議,編譯器可以自由地忽略它。 – Borgleader

+0

謝謝,但我知道。我的問題是關於內聯函數的最佳實踐以及編寫代碼的人是否做正確的事情。 – Aymen

+1

如果這些調用是有條件的並且很少發生(所以最頻繁的路徑繞過它們),這是非常有意義的。如果它們不是,它可能是有意義的,取決於函數(它們甚至可以被內聯;你不能通過查看源代碼知道編譯器會對它做什麼)。此外,您正在查看的代碼可能不是最佳使用「內聯」的最大參考材料。 – molbdnilo

回答

1

評論張貼的答案,要求:

如果誰寫的代碼的人認爲inline對性能產生任何有意義的影響,他顯然不是「做正確的事」。

性能來自正確的算法選擇並避免緩存未命中。

頭痛來自幼稚不成熟的優化技術,可在1991年

+3

我知道OP要求你發佈這個答案,但我不知道爲什麼。這是如何解決這個帖子中的問題的? –

+0

@Benjamin:這個問題是特定於我具體實現的。其中一些答案包含了一些有用的信息,但其中大部分都圍繞着同一個想法,以及如何使用不適合我的問題的內聯函數。儘管我不需要提出論據,但我希望澄清我的選擇。 – Aymen

+0

@Aymen這個答案沒有錯,但是它遠離這個線程中最好的答案。你問了一個基於你的內聯感覺問題的問題作爲一種性能提升,但它多年來對性能沒有任何影響。編譯器不僅可以拒絕實際內聯一個聲明爲這樣的函數,而且可以使用[整個程序優化](http://en.wikipedia.org/wiki/Interprocedural_optimization),甚至可以內聯沒有定義的函數翻譯單位。你的同事沒有做錯什麼。 –

3

我不知道是否有必要在內聯函數中嵌入函數調用。

當然是的。內聯對函數的調用仍然是一種優化,消除了該函數調用的成本,並允許在調用函數的上下文中進一步進行優化,而不管它是否調用其他函數。

其中上下文有什麼限制?

我不知道「context」是什麼意思;但對內聯函數可以做什麼沒有限制。聲明函數inline的唯一語義效果是允許多個相同的定義,並且需要在使用該函數的任何翻譯單元中定義。在所有其他方面,它與任何其他功能定義相同。

+0

許多材料表明,使用內聯函數的主要好處之一是避免調用函數引起的開銷。這就是爲什麼我發現從內聯函數調用兩個或三個函數有點奇怪。不過,我同意你的看法,無論如何都有一個函數調用的獲益。 – Aymen

1

編譯器將選擇何時內聯。你應該避免嘗試過早的優化,以犧牲公開你的實現爲代價。

編譯器可能能夠優化轉移正在調用的函數。即使您不使用inline關鍵字,它也可以通過優化標誌來實現。

使用inline關鍵字的時間是您希望在不需要使用鏈接庫的情況下在多個項目中使用僅包含頭文件的時間。實際上,這根本不意味着「內聯」,即使在編譯單元調用函數時也意味着「僅限一個定義」。

在你應該看看這個wiki提問/回答任何情況下:

Benefits of inline functions in C++?

0

首先,在C++中,「內聯」功能(在頭文件中聲明或打成這樣一個)就是對編譯器的建議。編譯器本身將決定是否實際使其內聯。

有三個原因,內聯函數:

  1. 推動新一輪的變量壓入堆棧是昂貴的,如分支在程序中的新的點。
  2. 有時我們可以使用函數的中間體進行本地優化(儘管我不會指望它!)
  3. 將函數的定義放在頭文件(變通)中。

看看下面的例子

void NonInlinable(int x); 
inline void Inline() { NonInlinable(10);} 

這使得一噸的意義在線。我刪除了1個函數調用,所以如果NonInlinable非常快,那麼這可能是一個巨大的加速。所以無論我是否打電話功能,我都可能想要打電話。

現在另一個例子:

inline int Inline(int y) {return y/10;} 
//main 
... 
int x = 5; 
int y = Inline(5); 
int z = x % 10; 

模數和設計的操作通常是由相同的指令來計算。一個非常好的編譯器,可以在1個彙編指令中計算y和z! 魔術在我的腦海

所以,一個更好的問題要問的是,當我應該使用內聯函數:

  1. 當我要分開說明定義(非常好做法的可讀性,和過早優化是萬惡之源)。
  2. 當我想隱藏我的實現/使用良好的封裝。
1

它是一個完美的感覺。

考慮一個由兩個可能的執行分支組成的函數 - 一個快速路徑,當某些條件成立時(大部分時間)和一條慢路徑被激活。

內聯整個事情會導致代碼的大小增加很少。緩慢的路徑複雜性可能會阻止編譯器內聯函數。

如果您將慢速路徑變爲單獨的功能,就會打開一個有趣的機會。

它使內聯條件和快速路徑成爲可能,而慢路徑仍然是函數調用。內聯快速路徑可以避免大部分時間內的函數調用開銷。慢路徑已經很慢,因此通話開銷可以忽略不計。

2

我沒有看到內聯代碼不能包含函數調用的先驗原因。

旁白的論點,內聯插入代碼行,減少調用開銷,並允許本地/臨時優化。

例如,當用MyInline(false)調用時,可以很好地跳過inline void MyInline(bool Perform) { if (Perform) memset(); }

內聯還可以允許內聯函數調用,從而產生更多(微)優化機會。

+0

請問,你能澄清一下編譯器在哪些情況下可能決定內聯被調用的函數嗎?它們是否與用於內聯調用函數的規則完全相同? – Aymen

+1

@Aymen:這是依賴於編譯器的,可能會改變。沒有規則。 –

相關問題