編譯器是否可以在多個轉換單元中複製同一模板的實例化?複製C++模板實例
例如,如果你有一個在函數內部使用std:vector<int>
的a.cpp,並且b.cpp是同樣的東西,那麼在最終的二進制文件中是否有兩次std::vector<int>
的風險?
編譯器是否可以在多個轉換單元中複製同一模板的實例化?複製C++模板實例
例如,如果你有一個在函數內部使用std:vector<int>
的a.cpp,並且b.cpp是同樣的東西,那麼在最終的二進制文件中是否有兩次std::vector<int>
的風險?
正如sharptooth所說,最終的二進制文件只包含一個實例。但是,每次遇到編譯單元時,模板仍將被實例化。如果你想要一些編譯速度,在C++ 0x中我們得到了extern template
。它與普通的extern
變量一樣工作,因爲它必須在至少一個編譯單元中指定,但編譯器不會在該單元中實例化模板。有關更多信息,請參閱here和this draft(14.7.2 [temp.explicit])。
這可能會在項目正在編譯時發生,因此不同的.obj文件將具有相同實例的副本。當二進制文件被鏈接時,鏈接器將消除實例化的所有冗餘副本,所以最終的二進制文件將只有一個副本。
我認爲編譯器使用與普通類的成員函數相同的機制。它可以使它們成爲inline
,並且我認爲它會在鏈接器用來爲最終的二進制文件進行分類時留下信息。
唯一的區別是,編譯器「寫」的定義 - 這是一個模板的「實例」 - 但它設法做完全一樣的實例,而編譯a.cpp或b.cpp
這是可能的,但只有當你明確實例化它們,但你會得到一個鏈接錯誤:
// header.hpp
template< typename T >
class A
{
};
// source1.cpp
template class A<int>;
// source2.cpp
template class A<int>;
如果你沒有明確實例化的模板,那麼任何像樣的連接能輕鬆清除副本。
我沒有得到任何錯誤(編譯或鏈接)時,我的g ++ -std-C++ 11個這三個文件(我把一個main()中的一個)我同意,當不止一個顯式實例似乎應該有一個錯誤(根據文檔:http://en.cppreference.com/w/cpp/language/class_template – 2017-04-06 20:44:40
是的。這不是一個風險。你爲什麼認爲這是一種風險? (他們不會得到外部鏈接,除非你明確地在一個單獨的編譯單元定義方法體,AFAICT) – sehe 2011-04-04 11:02:54