模板编译与实例化浅析

编译整体过程(针对C/C++),

1.      预处理:包含宏替换,条件编译,include导入文件

2.      编译:  包含词法分析,语法分析,语义分析,中间代码生成与优化,生成汇编文件

3.      汇编:  将汇编文件编译成2进制的机器码

4.      链接:  将目标文件与外部符号进行链接,得到一个二进制可执行文件

 

当编译器遇到一个模板定义时,它并不生成代码。只有我们实例化出模板的一个特定版本时,编译器才会生成代码

一般情况,当我们调用一个函数时,编译器只需要掌握函数的声明。当我们使用一个类类型的对象时,类的定义必须可用,但是成员函数的定义不一定已经出现。因此,我们把类的定义和函数声明放在头文件,普通函数和类的成员函数放在源文件中。

但是对于模板来说,为了生成一个实例化版本,编译器需要掌握函数模板或类模板成员函数的定义,因此,我们也将模板的定义放在头文件里面。

 

模板编译错误时机

模板由于在实例化时才生成代码,所以这会影响其编译错误的时机。

一般来说分为三个阶段,

第一,  编译模板本身,这里主要是语法错误,就是词法分析么~

第二,  遇到模板使用,这个阶段主要检查实参数目,类型匹配等。

第三,  模板实例化,这个阶段最容易暴露问题,根据编译器管理实例化情况,可能在链接时才出现错误。

可能大家对第二个和第三个阶段区别上比较困难,我们这样理解:

第一阶段,词法分析就是关键字,标识符什么的有没有拼写错误。

第二阶段,遇到模板就类似于语法分析,语法分析就是检查你这个句子是否合理通顺被,参数数量不对很明显不符合语法对吧

第三阶段,实例化就依赖于编译器,不过我们这里可以理解为在语义分析之后,你的代码可能存在类型不匹配的情况,只有在真正执行代码的时候才会发现,所以可能出现在链接执行的时候。

比如一个返回最大值的函数max

Template T  max(const T &a,const T&b)

{

   If(a

   If(a>b) return a;

   If(a==b) retun a;

我们定义一个类 DataNum  da1,da2;

Max(da1,da2);

结果在实例化的时候就可能是错误的,因为我们没有给DataNum类定义重载运算符“<”

 

所以,由于模板被使用时才会实例化这一特性,相同的实例可以出现在多个文件对象中。这样对大文件系统可能会产生很大的开销,C++11新标准中可以通过显示实例化来避免。

Blob.cpp

extern  template class  Blob

extern  template int  compare(const &int,const&int);

Blob  b1,b1;

Blob  bs1 ={1,2,3,4,5};//新标准支持列表初始化

Blob  bs2(bs1);

Int I =compare(bs1[1],bs1[2]);

 

Template.cpp

template  int compare(const &int,const &int);

template  class Blob

 

由于在Blob.cpp文件中使用了extern,所以其实例化的位置在其他文件,也就是Template.cpp.

而bs1,bs2是int类型的,没有extern声明,所以都是在Blob里面就已经实例化了。

 


转载于:https://www.cnblogs.com/soft4/p/5078724.html

你可能感兴趣的:(c/c++)