0

根據我的理解,內聯函數可以在頭文件中以及在源文件中(使用inline關鍵字),默認情況下,頭文件中定義的memeber函數被編譯器內聯使用。共享庫的cpp文件中的內聯函數

我的問題是下面的源文件, add.h

#ifndef ADD_H 
#define ADD_H 
class Add { 
    public: 
     int add(int a, int b); 
}; 
#endif /* ADD_H */ 

add.cpp

#include <iostream> 
#include "add.h" 

inline int Add::add(int a, int b) { 
    std::cout << "FUNC: " << __func__ << std::endl; 
    return a + b; 
} 

的main.cpp

#include "add.h" 

int main() { 
    Add a; 
    a.add(6,7); 
    return 0; 
} 

如果我編譯add.cpp和main.cpp

g++ -c add.cpp 
g++ -c main.cpp 
g++ main.o add.o 

它抱怨

main.o: In function `main': 
main.cpp:(.text+0x1a): undefined reference to `Add::add(int, int)' 
collect2: error: ld returned 1 exit status 

看着add.o符號,

 U __cxa_atexit 
       U __dso_handle 
000000000000003d t _GLOBAL__sub_I_add.cpp 
0000000000000000 t __static_initialization_and_destruction_0(int, int) 
       U std::ios_base::Init::Init() 
       U std::ios_base::Init::~Init() 
0000000000000000 r std::piecewise_construct 
0000000000000000 b std::__ioinit 

它並沒有在它添加功能,我認爲是因爲該函數是內聯的.cpp。我的問題是,當我們共享庫時,是否需要在頭文件中定義內聯函數(示例中爲add.h),以便使用該庫的源文件(示例中的main.cpp)獲得內聯在obj創建本身上的函數? 在鏈接中使用-flto時沒有什麼區別,因爲函數不在add.o中?

+1

不,不,不。如果函數內聯 - 它是內聯的。如果函數是在.h頭文件或.cpp源文件中定義的,則無關緊要;它是否是.dll/.so共享庫或.exe可執行文件無關緊要。有一點需要注意:我爲什麼會收到LNK2019解析的外部爲我的內聯函數?(https://blogs.msdn.microsoft.com/oldnewthing/20130509-00/?p=4413/) – paulsm4

+0

你必須要在使用-flto編譯時間也一樣。你嘗試過嗎? – kchoose2

回答

3

如果你在頭文件中定義一個函數,每個源文件#include s表示頭獲取功能的副本。您會收到來自鏈接器的投訴,其中存在重複的定義。

如果你在一個頭文件馬克它inline定義一個函數,每一個源文件#include s表示頭獲取功能的副本,但你告訴沒關係的編譯器和連接器榮獲抱怨。

如果你在一個源文件中定義一個函數並且不標記它inline它對其他源文件中的代碼是可見的,所以他們可以調用該函數。

如果您在源文件中定義了一個函數並將其標記爲inline,那麼對其他源文件中的代碼不可見。這就是問題所在:Addadd.cpp中定義,它的標記爲inline,因此它對main.cpp不可見。您可以刪除inline或將定義從add.cpp移動到add.h。如果將它移動到add.h,則可以保持原樣並將其放在類定義之後,或者直接在類定義中寫入,而不是將其標記爲inline

鏈接器優化與此完全分開。在形式上,inline的意思是「如果可以的話就可以擴展這個函數」,但是編譯器通常比你應該做的更好。鏈接器優化可以擴展函數內聯,而不考慮關鍵字inline,而不考慮其他文件的可見性。但是代碼必須是正確的,所以你必須通過修復代碼來解決缺失的符號,而不是試圖強制鏈接器優化。

+0

我認爲「鏈接器優化」是指鏈接時優化,它由編譯器執行,而不是鏈接器。你所提到的「內聯」的「正式」定義遠不是正式的。 –

2

您可以將函數定義放在標題中。如果它是在類定義中定義的,則暗示它是內聯的。

有一個很好的回答這個問題here

+0

這就是我現在正在做的,這是我的問題,是唯一的方法? – Randolf

+2

啊,我的壞,我必須剔除那部分。在這種情況下,這裏有一個類似的問題和一個很好的解釋:http://stackoverflow.com/questions/3992980/c-inline-member-function-in-cpp-file –

+0

感謝您的鏈接,我認爲如此,然後我的問題的第二部分是與-flto鏈接時間優化,可能是一個選項? – Randolf