2015-07-01 107 views
1

讓我們想象一下,包含blah.h頭文件:編譯器是否會在沒有主體的情況下內聯函數?

// A declaration without any code. We force inline 
__attribute__((always_inline)) void inline_func(); 

而且包含blah.cpp源文件:

#include "blah.h" 

// The code of the inline function 
void inline_func() { 
    ... 
} 

// Use the inline function 
void foo() { 
    inline_func(); 
} 

的問題是,將編譯器實際上內聯inline_func()?代碼應該與聲明一起使用,還是可以分開使用?

  • 假設沒有LTO
  • 注意在inline_func()
+4

他們將與LTO內聯,這可能會變得非常平常(也許稍後會隱式啓用)。 **這種內聯是LTO的定義** –

回答

1

您需要在內聯應該發生時提供正文。

I.e.如果你有下列文件:

inlineFunc.h 
inlineFunc.c 
main.c 

你編譯:

compile inline.c 
compile main.c 
link innline.o mcompile inline.c 

編譯main.c中 鏈接innline.o main.o yourCoookProgramain.o yourCoookProgram

沒有辦法inlineFuncmain.c中得到內聯,但可以內聯inlineFunc.c中的inlineFunc

正如Paolo提到的,inline只是編譯器的一個提示,然而一些編譯器也有辦法強制inining,即對於gcc你可以使用__attribute__(always_inline)。請在這裏討論gcc如何處理內聯。

An interesting sitenote

編譯主()時

警告在這種情況下,foo的定義出具()不是 可用。但是,使用-O2或更好的優化時,gcc會執行一種「反向內聯」,意思是 甚至可以將源文件中更進一步的函數定義嵌入到調用者中。因此,一旦使用至少-O2優化,警告 就會消失。是否有 任何特定的選項負責此行爲?我想 即使使用-O1或-O0啓用「反向內聯」。

+0

我用一個非常具體的例子來描述這個問題。在這個例子中,身體在實例化時是已知的。讓我們堅持到 –

+0

@ P.ChristopoulosCharitos:在這種情況下我說過'ilineFunc.c'適用:如果身體裏的時候知道這在技術上是可能的內聯。正如其他答案所述,'inline'關鍵字僅僅是一個提示,請參閱上面的答案,瞭解如何強制gcc進行內聯。 – ted

1

井(GCC)力直列裝飾,它依賴。在你的例子中,它將被內聯,因爲函數的定義與它使用的翻譯單元位於同一個翻譯單元中。否則,如果沒有LTO是可能的,並且在編譯時該函數的定義對編譯器不可用,則不,該函數將不被內聯。


此前答案

答案是:這取決於。這取決於編譯器,它也可能取決於編譯器的配置(1)(2)

參見inline description at cppreference.com(以下引用):

inline關鍵字的意圖是作爲指示器,以該函數的內聯取代優於函數調用優化,即,代替執行調用CPU指令以將控制轉移到功能體,則執行功能體的副本而不產生呼叫。這樣可以避免由函數調用(複製參數和檢索結果)所產生的額外開銷,但可能會導致更大的可執行文件,因爲函數的代碼必須重複多次。 由於關鍵字內聯的這種含義不具有約束力,因此編譯器可以自由使用內聯替換來對內聯未標記的任何函數進行內聯替換,並且可自由生成對內聯標記的任何函數的函數調用。這些選擇不會改變上述多個定義和共享靜態的規則。

+0

這是內聯的定義。該示例強制內聯。 –

+0

你說得對。但問題標題和標籤非常普遍,所以我以更一般的方式得到了問題。 –

2

內聯是一個兩步過程: *是否有可能? *這是否值得?

第一步相當簡單的由編譯器決定,第二步是更復雜的啓發式。因此,只考慮可能的優化的好處是有意義的。

always_inline意味着第二步被忽略。它不影響首先考慮。現在,您也已經聲明LTO已被禁用,這意味着首先考慮內聯功能的限制。這表明LTOalways_inline是非常不相關的,因爲它們影響兩種不同的內聯注意事項。

無論如何,LTO並不重要。正在審議的兩項職能在同一翻譯股。似乎沒有其他限制,例如遞歸,庫調用或其他可觀察的副作用。這意味着應該可以內聯,因爲這是唯一的考慮因素,所以應該內聯。

相關問題