C++ 理解c+中的模板时出现问题+;

C++ 理解c+中的模板时出现问题+;,c++,templates,compiler-construction,C++,Templates,Compiler Construction,在使用模板函数之前,不会编译模板代码。但是它在哪里保存编译后的代码呢?它是否保存在最初使用模板函数的对象文件中 比如说,, main.cpp正在从文件test.h调用模板函数,编译器生成一个对象文件main.o, 模板函数是否在主.o文件中?因为模板代码不是内联的,是吗?它总是内联的(意思是,它总是内部链接,具有内联语义)。事实上,它可能不是内联的,就像内联函数一样,但模板不是代码。它是一个“制作代码的模板”。因此,除特殊情况外,它通常位于标头中,请参见下文 有一个想法是制作其他东西,代号为“导

在使用模板函数之前,不会编译模板代码。但是它在哪里保存编译后的代码呢?它是否保存在最初使用模板函数的对象文件中

比如说,, main.cpp正在从文件test.h调用模板函数,编译器生成一个对象文件main.o, 模板函数是否在主.o文件中?因为模板代码不是内联的,是吗?

它总是内联的(意思是,它总是内部链接,具有内联语义)。事实上,它可能不是内联的,就像内联函数一样,但模板不是代码。它是一个“制作代码的模板”。因此,除特殊情况外,它通常位于标头中,请参见下文

有一个想法是制作其他东西,代号为“导出关键字”。它已从标准中删除

特殊情况:您可以将模板实例化编译成一个对象文件,而无需使用它们。这是避免所有模板代码内联的唯一方法。 这是如何做到的:

template class std::vector<MyClass>;
模板类std::vector;
这将强制编译器在当前位置实例化模板。C++0x将具有强制编译器不执行该操作的语法,并使链接器在别处搜索模板实例化:


extern模板类std::vector;//仅C++0x

您的意思是实例化的,而不是编译的。编译时,编译器会找出代码使用的每个版本,并(在目标文件中)安装所有必需的版本。

这完全取决于编译器的实现。大多数编译器将围绕、内联或类似cpp的文件生成代码,然后使用这些文件进行编译。有时,通过优化设置,一些编译器甚至会重用相同的代码,而不是为每个cpp重新创建代码


因此,您必须查看编译器的文档以了解更多详细信息。

是的,模板函数代码在
main.o
文件中发出。其中一些代码可能是内联的,就像任何其他代码可能是内联的一样,但一般来说,模板的代码是在实例化模板的任何文件中发出的。将其视为首先实例化模板代码以生成正常的非模板函数,然后使用编译器应用于任何其他函数的任何内联和优化来编译这些函数

当相同的模板实例化(例如,
std::vector
)发生在多个编译单元(
.cpp
文件)中时,会有一点困难,因为代码在每个编译单元中实例化。有各种各样的方法来处理这个问题,有时涉及链接阶段的清理步骤,其中重复的模板实例化被解析为单个模板实例化;您的编译器手册可以提供有关如何处理这种情况的详细信息。

即使从未实例化模板代码,也会对其进行编译。否则,无法要求编译器为此发出诊断:

template< typename T >
void f()
{
  blah
}
模板
void f()
{
废话
}
模板编译分两个阶段进行。除了基本检查之外,依赖于模板参数的所有内容都只能在实例化模板并用实际类型填充形式参数时进行检查。比如说这里,

template< typename T >
void f()
{
  typename T::nested_type x;
}
模板
void f()
{
typename T::嵌套的_类型x;
}

只有在实例化模板并为
T
提供实际类型后,才能检查
T::nested_type
。但是,在编译器遇到模板定义时,会执行一个基本检查(“给定
T::nested_type
是一个类型,这是有效的变量定义吗?”)。(这就是为什么需要
typename
的原因,顺便说一句。根据
T
T::nested_type
的不同,
T::nested_type
也可以是
T
的成员名或静态数据成员名,这将使
T::nested_type x;
成为语法错误。因此,我们必须告诉编译器将
T::nested_type
视为类型。)

它不一定是内联的。它是在编译单元中实例化的,可以是内联的,但也可以不是。export关键字与内联无关,而是以编译的形式提供模板,供客户机代码稍后实例化。是什么让您认为模板代码不是内联的?尝试在启用优化的情况下编译一个简单的示例,并反汇编结果。因此,使用未使用的虚拟变量创建模板类与创建类并将所有内容放入头文件不同。后者将是内联的,模板类取决于编译器如何使用它?@hidayat:No。相同的规则适用于“普通”类和类模板。重复:我认为在链接时可以合并节是对象文件格式的标准功能。我认为至少有一个系统调用它们
COMDAT
sections:(IIRC一些链接器甚至会检查这些部分是否相同以捕获一些错误。)这是实际的正确答案,而不是OP接受的答案。