模板的编译是如何工作的?
我正在阅读一本关于模板如何工作的书,我无法理解有关模板的说明。
上面写着
当编译器看到模板定义时,它不会生成代码。它仅在我们实例化模板的特定实例时生成代码。只有在使用模板时(而不是在定义模板时)才会生成代码,这一事实会影响我们如何组织源代码以及在检测到错误时……要生成实例化,编译器需要具有定义函数模板或类模板成员函数的代码。因此,与非模板代码不同,模板的标头通常包括定义和声明。
生成代码到底是什么意思?我不明白编译函数模板或类模板与常规函数或类有什么不同。
解决方案
编译器为模板类实例化中给定的特定类型生成代码。
如果您将模板类声明为
template<typename T>
class Foo
{
public:
T& bar()
{
return subject;
}
private:
T subject;
};
例如,一旦您有了以下实例化
Foo<int> fooInt;
Foo<double> fooDouble;
这些将有效地生成与您定义的类相同的可链接代码
class FooInt
{
public:
int& bar()
{
return subject;
}
private:
int subject;
}
和
class FooDouble
{
public:
double& bar()
{
return subject;
}
private:
double subject;
}
并实例化变量,如
FooInt fooInt;
FooDouble fooDouble;
关于模板definitions(不要与declarations混淆,不管是什么模板)需要与头文件(包括)一起看到这一点,原因非常清楚:
如果没有看到definition,编译器无法生成此代码。但它可以引用最先出现在链接阶段的匹配实例化。
非模板成员函数具有什么使其能够 在标头外部定义,而模板函数不定义 有吗?
非模板类/成员/函数的声明为链接器提供了预定义的入口点。该定义可以从编译的目标文件(==.cpp==compilation unit)中看到的单个实现中提取。 相反,模板化类/成员/函数的声明可以从给定相同或不同模板参数的任意编译单元实例化。这些模板参数的定义需要至少查看一次。它可以是通用的,也可以是专用的。
请注意,您可以为特定类型专门化模板实现(包括在标题中或在特定的compilation unit中)。 如果您希望在compilation units之一中为模板类提供专门化,并且不将模板类与专门化以外的类型一起使用,那么这也足以将它们链接在一起。我希望此示例有助于澄清编译器所做的努力和区别。
相关文章