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())时,我没有收到任何错误(编译或链接)。我同意当出现多个显式实例化时会出现错误(根据文档: