2011-03-25 19 views
6

我可以理解它是如何工作的,如果他們內聯。但如果他們不是,它是如何工作的?所有的目標文件都得到自己的副本,例如函數模板呢?模板如何工作,它們是否總是內聯?

+0

這些模板用於生成代碼。如果您使用模板,則會生成並使用類/函數。編譯器可以使用相同的參數刪除多個模板實例,但不能保證。我沒有看到內聯的鏈接。 – knivil 2011-03-25 10:46:45

回答

4

模板將在inline的標準含義,內聯這與「一個定義規則」更有關係,而不是實際的代碼內聯。也就是說,如果模板函數定義在多個翻譯單元中,鏈接器不會投訴,它只會選擇一個(注意:隨機一個,如果您在不同的翻譯單元中提供不同模板定義,則當前編譯器不會投訴! )並保留在最終的二進制文件中。

現在,與所有其他inline函數一樣,編譯器可以決定實際避免函數調用並在調用位置內聯函數是一個好主意,或者可能會確定它不是這樣一個好東西想法(大功能,一些編譯器不嵌套函數嵌套循環......無論原因),然後它不會執行實際的代碼內聯。

+0

而編譯器可能決定「內聯」未聲明爲「inline」的函數。當使用'gcc'時,我注意到這個函數沒有外部鏈接。 – Raedwald 2011-03-25 13:02:43

1

它取決於實現。

但通常,是的,每個對象文件都會獲取它們使用的每個擴展函數的副本。 然後鏈接程序在鏈接時注意到這一點,並確保函數中只有一個副本被放入最終的可執行文件中

2

取決於編譯器,但是我看過的每一個都創建了一個函數,然後可以調用使用替代模板參數來生成每個變量的代碼。 (他們是在一種特殊的方式但是裝飾,以防止其他問題)

template <typename T> T Max(T a, T b) 
{ 
    return a > b ? a : b; 
} 

時爲Max<int>Max<float>調用,而不是內聯,編譯器生成:

一個非常簡單的例子

然後
int Max(int a, int b) 
{ 
    return a > b ? a : b; 
} 

float Max(float a, float b) 
{ 
    return a > b ? a : b; 
} 

這是停留在對象的開始,然後引用,那麼同樣是對一些內聯(在MSVC)

2

做得太它依靠。一些比較流行的實現是 在每個對象文件 中生成實例化代碼的副本,其觸發實例化,並且計數連接器到 除了一個之外全部丟棄。其他編譯器使用某種 存儲庫,其中實例化被存儲;如果 實例化已經存在,編譯器不會打擾 重新生成它。此解決方案速度更快,並且使用比第一種解決方案少的磁盤,但是 也很難更正。 (編譯器必須產生一個新的實例 不僅如果不存在,但如果任何 實例取決於文件的發生了變化。)

0

模板是真的非常非常先進的宏(#定義)

參數是在編譯時與傳遞的值代替。真的很棒的概念,也非常好。

+0

宏不應該與模板混在一起,並且已經混淆了它們的概念:宏在第一個轉換步驟中正確擴展,即它們可以生成要傳遞給C++分析器的標記。這是不可能的模板。 – 2011-12-19 13:12:01

0

模板對自己來說是一種完整的語言。他們是圖靈完整的,但「程序」在編譯時運行。它們是在編譯時替換對象類型的代碼工廠,並在編譯時組裝類,函數等。所以你可以把它看作一種類型安全的,C++兼容的大規模預處理語言。執行的結果輸出是純粹的C++代碼,然後編譯器可以像處理所有其他代碼一樣處理它。

編譯器通常忽略內聯,因爲很少有程序員可以真正知道什麼時候最好,哪些還沒有離開彙編。

相關問題