C++ 重复的c++;模板实例化
编译器是否可以跨多个翻译单元复制同一模板的实例化C++ 重复的c++;模板实例化,c++,templates,C++,Templates,编译器是否可以跨多个翻译单元复制同一模板的实例化 例如,如果a.cpp在一个函数中使用了std:vector,而b.cpp使用的是相同的东西,那么在最终二进制文件中是否存在两次std::vector的风险?这可能发生在编译项目时,因此不同的.obj文件将具有相同实例化的副本。链接二进制文件时,链接器将消除实例化的所有冗余副本,因此最终二进制文件将只有一个副本。在编译项目时可能会发生这种情况,因此不同的.obj文件将具有相同实例化的副本。当二进制文件被链接时,链接器将消除实例化的所有冗余副本,因此
例如,如果a.cpp在一个函数中使用了
std:vector
,而b.cpp使用的是相同的东西,那么在最终二进制文件中是否存在两次std::vector
的风险?这可能发生在编译项目时,因此不同的.obj文件将具有相同实例化的副本。链接二进制文件时,链接器将消除实例化的所有冗余副本,因此最终二进制文件将只有一个副本。在编译项目时可能会发生这种情况,因此不同的.obj文件将具有相同实例化的副本。当二进制文件被链接时,链接器将消除实例化的所有冗余副本,因此最终二进制文件将只有一个副本。我认为编译器使用与普通类的成员函数相同的机制。它可以使它们内联
,我认为它会留下链接器用来为最终二进制文件排序的信息
唯一的区别是编译器“编写”定义,即模板的“实例化”,但它在编译a.cpp或b.cpp时能够实现完全相同的实例化。我认为编译器使用的机制与普通类的成员函数相同。它可以使它们
内联
,我认为它会留下链接器用来为最终二进制文件排序的信息
唯一的区别是编译器“编写”定义——即模板的“实例化”——但它在编译a.cpp或b.cpp时能够实现完全相同的实例化,正如夏普顿所说,最终的二进制文件将只包含一个实例化。但是每次在编译单元中遇到模板时,它们仍然会被实例化。如果您想要一些编译速度,在C++0x中,我们可以得到
extern模板
s。它的工作原理与普通的extern
变量类似,因为它必须在至少一个编译单元中指定,但编译器不会在此单元中实例化模板。有关更多信息,请参见和(14.7.2[temp.explicit])。正如sharptooth所说,最终二进制文件将只包含一个实例化。但是每次在编译单元中遇到模板时,它们仍然会被实例化。如果您想要一些编译速度,在C++0x中,我们可以得到extern模板
s。它的工作原理与普通的extern
变量类似,因为它必须在至少一个编译单元中指定,但编译器不会在此单元中实例化模板。有关更多信息,请参阅和(14.7.2[temp.explicit])。这是可能的,但仅当您显式实例化它们时,您将得到链接器错误:
// header.hpp
template< typename T >
class A
{
};
// source1.cpp
template class A< int >;
// source2.cpp
template class A< int >;
//header.hpp
模板
甲级
{
};
//source1.cpp
模板类别A;
//source2.cpp
模板类别A;
如果您没有显式实例化模板,那么任何合适的链接器都会很容易地消除副本。这是可能的,但只有当您显式实例化模板时,链接器才会出错:
// header.hpp
template< typename T >
class A
{
};
// source1.cpp
template class A< int >;
// source2.cpp
template class A< int >;
//header.hpp
模板
甲级
{
};
//source1.cpp
模板类别A;
//source2.cpp
模板类别A;
如果您没有显式地实例化模板,那么任何合适的链接器都很容易消除副本。是的。这不是风险。你为什么认为这是一种风险?(除非在单独的编译单元AFAICT中明确定义方法体,否则它们不会获得外部链接)是的。这不是风险。你为什么认为这是一种风险?(除非您在单独的编译单元AFAICT中明确定义方法体,否则它们不会获得外部链接)当I g++-std-c++11这三个文件(我将一个main()放在一个文件中)时,我不会得到任何错误(编译或链接)。我同意当出现多个显式实例化时会出现错误(根据文档:当I g++-std-c++11这三个文件(我在其中放了一个main())时,我没有收到任何错误(编译或链接)。我同意当出现多个显式实例化时会出现错误(根据文档: