模板的编译是如何工作的?

新手上路,请多包涵

我正在阅读一本关于模板如何工作的书,但我很难理解对模板的这种解释。

它说

当编译器看到模板的定义时,它不会 生成代码。它仅在我们实例化模板的特定实例时生成代码。代码仅在我们使用模板时生成(而不是在定义模板时)这一事实会影响我们组织源代码的方式以及检测到错误的方式…要生成实例化,编译器需要具有定义函数模板或类模板成员函数。因此,与非模板代码不同,模板的标头通常包括定义和声明。

“生成代码”到底是什么意思?与常规函数或类相比,我不明白编译函数模板或类模板有什么不同。

原文由 FrostyStraw 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 776
1 个回答

编译器为模板类实例化中给出的特定类型 生成 代码。

例如,如果您有一个模板类声明

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;

关于模板 定义(无论模板如何都不要与 声明 混淆)需要与头(包含)文件一起查看这一点,原因很清楚:

编译器无法在没有看到 定义 的情况下生成此代码。它可以指的是在链接阶段首先出现的匹配实例。

非模板成员函数有什么允许在模板函数没有的标头之外定义它?

非模板类/成员/函数的声明为链接器提供了预定义的入口点。该定义可以从已编译目标文件(== .cpp == 编译单元)中看到的单个实现中得出。

相反,模板化类/成员/函数的声明可以从给定相同或不同模板参数的任意编译单元实例化。这些模板参数的定义至少需要查看一次。它可以是通用的或专用的。

请注意,无论如何您都可以为特定类型专门化模板实现(包含在标头中或在特定的 编译单元 中)。如果您要在您的一个 编译单元 中为您的模板类提供专门化,并且不要将您的模板类与除专门化之外的类型一起使用,那么将它们链接在一起也应该足够了。

我希望这个示例有助于阐明编译器的不同之处和所做的努力。

原文由 πάντα ῥεῖ 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题