2009-08-13 44 views
6

內聯函數只是一個編譯器的請求,它將整個內聯函數的主體插入到使用該函數的代碼中的每個地方。內嵌函數(何時插入)?

但編譯器如何決定是否應該插入它?它使用哪種算法/機制來決定?

感謝,

納文

+1

它不是一個請求 - 它的建議。這個決定取決於編譯器 – chester89 2009-08-13 12:38:58

回答

4

一些常見的方面:

  • 編譯器選項(調試通常建立沒有內聯,和大多數編譯器有選項覆蓋內嵌聲明嘗試內聯全部或全部)
  • 適合的調用約定(例如,可變長度函數通常不內聯)
  • 適合內聯:取決於函數的大小,函數的調用頻率,通過內聯獲得的增益,和優化集(速度與代碼大小)。通常情況下,微小的功能有最大的利益,但如果它被稱爲只是一次
  • 內嵌調用深度和遞歸設置

第三可能是你的問題的核心了巨大的功能可能被內聯,但是這是真的「編譯器特定的啓發式」 - 你需要檢查編譯器文檔,但通常他們不會提供太多的保證。 MSDN有一些(有限的)MSVC信息。除了微不足道(例如簡單的getter和非常原始的函數)之外,內聯這樣的不再有幫助了。呼叫指令的成本下降,分支預測大大改善。

編譯器知道

內聯的大好機會被移除代碼路徑不會被考慮 - 作爲一個極端的例子:

inline int Foo(bool refresh = false) 
{ 
    if (refresh) 
    { 
     // ...extensive code to update m_foo 
    } 
    return m_foo; 
} 

一個好的編譯器會內聯Foo(false),但不Foo(true)

隨着鏈接時代碼生成,Foo可以駐留在一個.cpp(不帶inline declararion),並Foo(false)仍然會內聯,如此反覆直列這裏只有邊際效應。


總結:在很少的情況下,您應該嘗試通過放置(或省略)內聯語句來手動控制內聯。

-2

如果你寫的 「內聯」 的功能開始它插入?

+2

不需要。它只是一個請求。 – Naveen 2009-08-13 11:19:12

+0

對於C++來說,它基本上只意味着如果不同的目標文件包含相同的定義,它不會導致鏈接器錯誤。這是標準所要求的。不管函數是否真的被內聯,使用'inline'或不使用'inline'通常都沒有任何關係。 – gimpf 2009-08-13 11:48:50

+0

至少有評論通知人:) – ufukgun 2009-08-13 12:46:12

2

我所知道的內聯函數(以及很多其他C++的東西)是here。另外,如果你將注意力放在每個編譯器的啓發式來決定是否在函數中,那麼這是依賴於實現的,你應該看看每個編譯器的文檔。請記住,啓發式也可以根據optimitation的水平而改變。

1

我敢肯定,大多數編譯器根據函數的長度(編譯時)以字節爲單位決定,以及使用頻率與優化類型(速度與大小)的關係。

1

我只知道幾個標準:

  • 如果直列滿足遞歸 - 內聯將被忽略。
  • 開關/時/在大多數情況下會導致編譯器忽略內嵌
1

這取決於編譯器。這裏是(第一部分)什麼GCC手冊說:

 
    -finline-limit=n 
      By default, GCC limits the size of functions that can be inlined. 
      This flag allows the control of this limit for functions that are 
      explicitly marked as inline (i.e., marked with the inline keyword 
      or defined within the class definition in c++). n is the size of 
      functions that can be inlined in number of pseudo instructions (not 
      counting parameter handling). The default value of n is 600. 
      Increasing this value can result in more inlined code at the cost 
      of compilation time and memory consumption. Decreasing usually 
      makes the compilation faster and less code will be inlined (which 
      presumably means slower programs). This option is particularly 
      useful for programs that use inlining heavily such as those based 
      on recursive templates with C++. 

      Inlining is actually controlled by a number of parameters, which 
      may be specified individually by using --param name=value. The 
      -finline-limit=n option sets some of these parameters as follows: 

      @item max-inline-insns-single 
      is set to I/2. 
      @item max-inline-insns-auto 
      is set to I/2. 
      @item min-inline-insns 
      is set to 130 or I/4, whichever is smaller. 
      @item max-inline-insns-rtl 
      is set to I. 

      See below for a documentation of the individual parameters 
      controlling inlining. 

      Note: pseudo instruction represents, in this particular context, an 
      abstract measurement of function's size. In no way, it represents 
      a count of assembly instructions and as such its exact meaning 
      might change from one release to an another. 
2

以下是在FAQ可以通過Sun Studio 11編譯器:

編譯器生成的內聯函數作爲普通的可調用函數(脫線)時以下任何條件爲真:

  • 用+ d編譯。
  • 用-g編譯。
  • 函數的地址是必需的(與虛函數一樣)。
  • 該函數包含編譯器不能內聯生成的控制結構。
  • 該功能太複雜。

據「clamage45」的「該編譯器不能生成的內聯控制結構」的響應於該post是:

  • 功能包含禁止構建體,如環,開關或轉到

另一個列表可以找到here。由於大多數其他的答案中所指定的試探將是100%的編譯器特定的,從我讀過,我認爲以確保功能實際上是內聯,你需要避免:

  • 局部靜態變量
  • 循環結構
  • switch語句
  • 的try/catch
  • 轉到
  • 遞歸
  • 當然過於複雜(的無論是m eans)