问题理解c ++中的模板

时间:2010-03-30 13:55:26

标签: c++ templates compiler-construction

在使用模板函数之前,不会编译模板代码。但它在哪里保存已编译的代码,是否保存在首先使用模板函数的目标文件中?

例如, main.cpp从文件test.h中调用模板函数,编译器生成一个目标文件main.o, 模板函数是否在main.o文件中?因为模板代码没有内联,是吗?

5 个答案:

答案 0 :(得分:4)

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

因此,您需要查看编译器的文档以获取更多详细信息。

答案 1 :(得分:3)

是的,模板功能代码在main.o文件中发出。其中一些可能是内联的,因为任何其他代码可能都是内联的,但通常,模板的代码是在模板实例化的任何文件中发出的。可以将它想象为首先实例化模板代码以生成普通的非模板函数,然后使用编译器应用于任何其他函数的内联和优化来编译这些函数。

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

答案 2 :(得分:1)

模板代码编译的,即使它从未实例化过。否则,不能要求编译器为此发出诊断信息:

template< typename T >
void f()
{
  blah
}

模板编译发生在两个阶段中。除了基本检查之外,只有在实例化模板并且使用实际类型填充形式参数时,才能检查依赖于模板参数的所有内容。例如,这里

template< typename T >
void f()
{
  typename T::nested_type x;
}
只有在实例化模板并为T::nested_type提供实际类型后,才能检查

T。但是,基本检查(“给定T::nested_type是一种类型,这是一个有效的变量定义吗?”)在编译器遇到模板定义时执行。 (这就是为什么typename是必需的,BTW。根据TT::nested_type可能也是T成员的名称或静态数据成员 - 这将是使T::nested_type x;语法错误。所以我们必须告诉编译器将T::nested_type视为类型的名称。)

答案 3 :(得分:0)

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

有一个想法是创造别的东西,代号为“export keyword”。它已从标准中移除。

特殊情况:您可以将模板实例化编译到目标文件中,而无需使用它们。这是避免内联所有模板代码的唯一方法。 这就是它的完成方式:

template class std::vector<MyClass>;

这将强制编译器在当前位置实例化模板。 C ++ 0x将有一个语法强制编译器执行此操作,并让链接器在其他位置搜索模板实例化:

extern template class std::vector<MyClass>; // C++0x only

答案 4 :(得分:0)

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