2012-05-10 21 views
82

由於模板是在頭文件中定義的,編譯器能夠確定內聯函數是否有利,它有什麼意義嗎?我聽說現代編譯器知道何時內聯函數並忽略inline提示。在模板中使用內聯關鍵字有意義嗎?


編輯:我想接受這兩個答案,但這是不可能的。要關閉我接受phresnel這個問題的答案,因爲它獲得多數選票,他是正式的權利,但正如我在評論中提到,我認爲小狗的和組件10的答案是正確之輩,從不同的角度來看。

問題出在C++語義上,在inline關鍵字和內聯的情況下不嚴格。 phresnel表示「如果你的意思是內聯寫入」,但inline的實際含義並不清楚,因爲它從原來的含義演變爲「阻止編譯器對ODR違規行爲嗤之以鼻」的指令爲Puppy說。

回答

65

這並非無關緊要。不,並不是每個功能模板默認爲inline。該標準是,即使在明確分工([temp.expl.spec])

有以下明確一下:

a.cc

#include "tpl.h" 

b.cc

#include "tpl.h" 

tpl。^ h(從顯專業化取):

#ifndef TPL_H 
#define TPL_H 
template<class T> void f(T) {} 
template<class T> inline T g(T) {} 

template<> inline void f<>(int) {} // OK: inline 
template<> int g<>(int) {} // error: not inline 
#endif 

編譯這個,等瞧:

g++ a.cc b.cc 
/tmp/ccfWLeDX.o: In function `int g<int>(int)': 
inlinexx2.cc:(.text+0x0): multiple definition of `int g<int>(int)' 
/tmp/ccUa4K20.o:inlinexx.cc:(.text+0x0): first defined here 
collect2: ld returned 1 exit status 

未公開inline時做顯式實例也可能導致的問題。

因此,在總結:對於非完全專用的功能模板,即那些攜帶至少一個未知類型,則可以省略inline,並沒有收到錯誤,但他們仍然不inline。對於完全的專業化,即只使用已知類型的專業,你不能忽略它。拇指的

擬議的規則:寫inline如果你的意思是,只是是一致的。它讓你更少思考是否或僅僅因爲可以。 (這條經驗法則符合Vandevoorde's/Josuttis's C++ Template: The Complete Guide)。

+0

明確的專業化是真的 - 它們就像普通的功能一樣。但是在這裏 - >'template inline T g(T){}'不需要內聯,你可以寫'template T g(T){}' – doc

+1

可以寫成true。但是這並不意味着內聯,即使它看起來像這樣。 Vandevoorde和Josuttis在_C++模板中也完全說明了這一點:完整的Guide_ –

+0

模板可以有多個定義(3.2/5) - > http://stackoverflow.com/a/10211420/205955我聲明這並不意味着它們是正式內聯的。但是,這一切都歸結於實踐。所以,從不同的角度來看,這兩個答案都是正確的。 – doc

21

這是無關緊要的。所有模板已經是inline - 更不用說,截至2012年,關鍵字inline的唯一用處是停止編譯器對ODR違規行爲的嘲諷。你是絕對正確的 - 你現在的編譯器會知道自己的內聯,甚至可以在翻譯單元之間這樣做。

+5

該標準沒有聲明所有模板都是內聯的。 –

+10

@phresnel:但是模板與'inline'標記的函數具有相同的語義(也就是說,多個等價的定義可以傳遞給鏈接器,它將選擇一個)。那不是內聯,是inline關鍵字的真正功能。 –

+0

@BenVoigt:我知道'inline'的ODR含義。也許有人在我的答案下面(或以上,根據選擇的排序)偷看。對於非專業模板,你當然是對的,但它在形式上是不一樣的。 –

1

正如你所建議的,inline是編譯器的暗示,僅此而已。它可以選擇忽略它,或者實際上,內聯沒有標記爲內聯的函數。

使用inline與模板曾經是一個(窮)方式來解決問題,每個編譯單元將爲同一個模板類創建一個單獨的對象,然後在鏈接時會導致重複問題。通過使用inline(我認爲)這個名字在不同的鏈接時會碰到不同的名字衝突,但代價很大。  

Marshall Cline explains it here比我還好。

+0

@Xeo:以前並不這樣。點擊這裏:http://gcc.gnu.org/onlinedocs/gcc-4.0.4/gcc/Template-Instantiation.html#Template-Instantiation我認爲最近發生了變化,這就是爲什麼我用過去式說話的原因。 –

+1

@Xeo:您​​能否指出標準中標明函數模板總是內聯的部分?因爲,他們不是。 –

+0

@ phresnel:有趣的,我可以發誓我已經閱讀過標準。也許我把它與功能模板從ODR中免除的事實混爲一談('§14.5.5.1p7&p8')。我的不好,我刪除了錯誤的評論。 – Xeo