02模板学习之函数模板的编译原理
可能下面不太好理解,建议可以参考【C++】模板(template)进阶,这篇内容的介绍好理解很多,个人也觉得比本篇容易理解。
1 函数模板编译的次数
编译器会对函数模板进行两次编译,在声明函数模板地方编译一次,在调用的地方再编译一次。
注:该结论是固定的,记住即可。
2 函数模板第一次编译后再被调用确定类型后,第二次编译如何生成函数
当函数模板声明后(声明即第一次编译)被调用时,出现不同的调用方式时(例如形参不同),编译器将模板生编译成多个函数(调用即第二次编译);若同样的调用方式,则不生成重复的函数,复用已经生成的函数。
代码例子讲解:
//声明后会进行第一次编译
template<class T>
int MyAdd(T a, T b){
return a+b;
}
int main(){
//此时编译器第二次编译会生成一个MyAdd(int int)的函数
int a=1;
int b=2;
MyAdd(a,b);
//此时编译器第二次编译会生成一个MyAdd(double double)的函数
double c=1.1;
double d=2.2;
MyAdd(c,d);
//再次调用,不会再生成,只会复用上面已经生成的函数
MyAdd(a,b);
return 0;
}
下面我们可以通过gcc的-S命令来查看:
首先了解一下gcc当地这两个选项先。
-S:执行到编译阶段停止。生成的后缀名默认为.s,会经历之前的阶段。
//注意与-c区别
-c:不执行前面的阶段,只在编译阶段编译并且在汇编阶段生成目标文件后跳过汇编和链接。生成的后缀默认为.o。所以很多人短说:只编译不汇编链接(但会在汇编阶段生成目标文件)。
g++或者gcc编译生成编译阶段的.s文件,因为.o根本无法看,都是二进制了,所以这里使用编译时的文件分析。
先找到main函数,然后再找到call,意思是代表调用的意思,然后对比发现,三个call中有两个函数名是一样的,所以模板在第二次编译时只生成了两个函数。