问题 重复的c ++模板实例化


编译器是否可以跨多个翻译单元复制同一模板的实例化?

例如,如果你有一个使用a的.cpp std:vector<int> 在函数内部,对于b.cpp来说,同样的事情是存在两次的风险 std::vector<int> 在最后的二进制?


7765
2018-04-04 10:44


起源

是。这不是风险。为什么你认为这是一种风险? (除非您在单独的编译单元AFAICT中明确定义方法体,否则它们不会获得外部链接) - sehe


答案:


正如sharptooth所说,最终的二进制文件只包含一个实例。但是每次在编译单元中遇到模板时,模板仍然会被实例化。如果你想要一些编译速度,在C ++ 0x中我们得到了 extern template秒。它像平常一样工作 extern 变量,因为它必须在至少一个编译单元中指定,但编译器不会在此单元中实例化模板。看到 这里 和 这个草案 (14.7.2 [temp.explicit])了解更多信息。


5
2018-04-04 10:59





这可能在项目编译时发生,因此不同的.obj文件将具有相同实例化的副本。当链接二进制文件时,链接器将消除实例化的所有冗余副本,因此结束二进制文件将只有一个副本。


6
2018-04-04 10:55





我认为编译器使用与普通类的成员函数相同的机制。它可以使他们 inline 我假设它留下了链接器用来为最终二进制文件排序的信息。

唯一的区别是编译器“写入”定义 - 即模板的“实例化” - 但它在编译a.cpp或b.cpp时设法完全相同的实例化


0
2018-04-04 10:57





这是可能的,但只有当您明确地实例化它们时,您才会收到链接器错误:

// header.hpp
template< typename T >
class A
{
};

// source1.cpp
template class A< int >;

// source2.cpp
template class A< int >;

如果您没有明确地实例化模板,那么任何合适的链接器都可以轻松地消除副本。


0
2018-04-04 12:21



我没有得到任何错误(编译或链接)当我g ++ -std -c ++ 11这三个文件(我把一个main()放在一个。)我同意当出现多个显式实例时应该有一个错误(根据文件: en.cppreference.com/w/cpp/language/class_template - Don Slowik