实现机制原理剖析

1. 编译器并不是把函数模板处理成能够处理任意类的函数

2. 编译器从函数模板通过具体类型来产生不同的函数

3. 编译器会对函数模板进行两次编译

(1)在声明的位置对模板代码进行编译

(2)在调用的位置对参数替换后的代码进行编译

示例

自己写的代码:

#include<iostream>
using namespace std;

template <typename T>    //声明位置,第一次编译
T  myswap(T a, T b)
{
    cout << "调用模板函数!!!" << endl;
    return 0;
}

int main()
{
    myswap(1,1);         //调用位置,第二次编译
    myswap('a','b');
    myswap(2.0,3.0);        
    
}

实际编译器处理后的代码:

#include<iostream>
using namespace std;

int     myswap(int  a, int b)
{
    cout << "调用模板函数!!!" << endl;
    return 0;
}

double  myswap(double a, double b)
{
    cout << "调用模板函数!!!" << endl;
    return 0;
}

char myswap(char a, char b)
{
    cout << "调用模板函数!!!" << endl;
    return 0;
}

int main()
{
    myswap(1,1);         
    myswap('a','b');
    myswap(2.0,3.0);        
}

理解

  1. 函数模板不是说只 一个函数 就可以实现对任意数据类型的操作,而是通过两次编译生成了满足我们调用需求所需要的所有代码。
  2. 函数模板使用后,编译器并不会一开始就生成所有处理任何类型的函数,而是通过实际的函数调用来生成。比如调用函数时,需要处理int型数据,就生成处理int型数据的函数,而没有用double型数据,就不会生成处理double型数据的函数。
  3. 编译器内部帮我们实现了大量重复操作,让程序员节省了大量代码