C++ 中的模板类是否在不同的编译单元中被多次编译?

Sam*_*rsa 6 c++ templates

假设我有以下代码:

// templateClass.h
#ifndef TEMPLATE_CLASS_H
#define TEMPLATE_CLASS_H

template <typename T>
class tClass
{
public:
  tClass();
};

#endif

// templateClassDef.inl
#ifndef TEMPLATE_CLASS_DEF_INL
#define TEMPLATE_CLASS_DEF_INL

template <typename T>
tClass<T>::tClass()
{
}

#endif

// normalClass.h
#include "templateClass.h"

class normal
{
public:
  normal();
};

// normalClass.cpp
#include "normalClass.h"
#include "templateClassDef.inl"

normal::normal()
{
  tClass<int> a;
}

// main.cpp
#include "templateClass.h"
#include "templateClassDef.inl"

#include "normalClass.h"

int main()
{
  tClass<int> a;
  normal b;

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

请注意,该inl文件没有像通常那样包含在标头中,而是包含在源文件中(我知道这不是标准方式......这只是一个示例)。请注意,normalcClass.cpp正在实例化tClass<int>, 也是如此main.cpp

我很好奇编译器是否每次遇到显式实例化时都必须从模板类构造实例化,考虑到它是相同的类型(即tClass<int>,即使两个实例化发生在单独的翻译单元(normalClass.cppmain.cpp)中?另外,这会增加编译时间吗(如果上一个问题的答案是肯定的,它将再次实例化它,那么这也应该是肯定的)?

xxb*_*bcc 3

一般来说,是的,模板类通常在编译器每次遇到时都会进行编译。

  • 链接器将删除每个实例化的所有副本,只保留一份副本。但是编译器无法知道您将链接哪些其他模块,因此它必须编译您使用的任何实例化,除非您使用“extern”承诺在链接时提供它。模板与内联函数一样,可以避免多重定义冲突;链接器只会选择一个副本来使用。ODR 规则仍然适用,所有具有相同名称的副本必须具有相同的行为,因此链接器选择哪一个并不重要。 (3认同)