对于一个交换函数虽然C支持函数重载我们可以对多个交换函数起相同的名字123456789101112voidSwap(int left,int right){inttemp left;left right;right temp;}voidSwap(double left,double right){doubletemp left;left right;right temp;}但是依然有不足的地方比如如果我们要交换其他类型比如char或者类类型那还是得再写一个交换函数这样原来写好的其他类型的交换函数就没有复用起来大大降低了效率。因此C引入了模板的概念通过模板即可实现一份代码交换不同数据。模板其实就是告诉编译器一个模子让编译器根据不同的类型利用该模子来生成代码。1.1.函数模板**泛型编程**在之前函数都是针对某个具体的类型比如intchar而泛型则是针对一个广泛的类型。模板则是泛型编程的基础。所以函数模板的参数并不是一个具体的类型只有当调用时才能确定具体的类型。其语法为12345//定义模板参数T可以用typename也可以使用classtemplatetypenameT1,typenameT2,......,typenameTn返回值类型 函数名(用泛型指定的参数列表){}以交换函数为例12345678910111213141516templatetypenameTvoidSwap(T left, T right){T temp left;left right;right temp;}intmain(){inta 10, b 20;doublec 1.1, d 2.2;Swap(a, b);Swap(c, d);cout a b endl;cout c d endl;}从反汇编可以看出这两个函数调用的并不是同一个函数这是因为函数模板不是一个实际的函数编译器不会为其生成可执行代码。当调用函数模板时编译器会对函数模板进行推演根据传入实参的类型推出T的类型然后实例化出不同类型的函数。1.1.1.两种函数模板的实例化用不同类型的参数使用函数模板时称为函数模板的实例化。1.隐式实例化让编译器根据实参推演模板参数的实际类型当有多个类型的实参而模板参数列表中只有一个T时编译器将无法推演出T的类型此时可以将实参进行类型强转有趣的是强转后需要用const T来接收因为强转后传入的并不是c而是c的临时变量这个临时变量是具有常属性的。2.显式实例化在函数名后的中指定模板参数的实际类型通过这种方式可以不让编译器推演类型而是使用我们指定的类型。当然对于类型不同的参数也要使用const T来接收。1.1.2.模板参数的匹配原则一个非模板函数可以和一个同名的函数模板同时存在调用的时候如果与非模板函数匹配编译器会优先调用非模板函数。如果非模板函数不匹配或者进行了实例化则会调用函数模板。1.2.类模板对于一个类的成员变量也可以使用模板这样在定义类对象的时候就可以实例化出具有不同类型的成员变量和成员函数的对象了。如果类模板中函数放在类外进行定义时需要加模板参数列表否则会找不到T。模板也不支持分离编译建议定义在一个文件中。以动态顺序表为例123456789101112131415161718192021222324252627282930313233343536373839templateclassTclassVector{public:Vector(size_tcapacity 10): _pData(newT[capacity]), _size(0), _capacity(capacity){}~Vector();//头插尾插等函数实现。。。size_tSize(){return_size;}T operator[](size_tpos){assert(pos _size);return_pData[pos];}private:T* _pData;size_t_size;size_t_capacity;};//类模板中函数放在类外进行定义时需要加模板参数列表否则会templateclassTVectorT::~Vector(){if(_pData)delete[] _pData;_size _capacity 0;}intmain(){Vectorint s1;Vectordouble s2;//实例化两个不同的类对象return0;}类模板实例化与函数模板实例化不同类模板实例化只能显示实例化需要在类模板名字后跟然后将实例化的类型放在中即可类模板名字不是真正的类而实例化的结果才是真正的类。二、STLSTL英文全称 standard template library中文可译为标准模板库或者泛型库其包含有大量的模板类和模板函数是 C 提供的一个基础模板的集合用于完成诸如输入/输出、数学计算等功能。STL有六大组件但主要包含容器、算法和迭代器三个部分。容器Containers用来管理某类对象的集合。各种数据结构如vector、list、deque、set、map等,用来存放数据从实现角度来看STL容器是一种class template。算法Algorithms用来处理对象集合中的元素各种常用的算法如sort、find、copy、for_each。从实现的角度来看STL算法是一种function template。迭代器Iterators用来在一个对象集合的元素上进行遍历动作。扮演了容器与算法之间的胶合剂共有五种类型从实现角度来看迭代器是一种将operator* , operator- , operator, operator–等指针相关操作予以重载的class template。所有STL容器都附带有自己专属的迭代器只有容器的设计者才知道如何遍历自己的元素。原生指针(native pointer)也是一种迭代器。仿函数行为类似函数可作为算法的某种策略。从实现角度来看仿函数是一种重载了operator()的class 或者class template。适配器一种用来修饰容器或者仿函数或迭代器接口的东西。空间配置器负责空间的配置与管理。从实现角度看配置器是一个实现了动态空间配置、空间管理、空间释放的class tempalte。STL存在以下缺陷STL库的更新太慢了。上一版靠谱是C98中间的C03基本一些修订。C11出来已经相隔了13年STL才进一步更新。STL现在都没有支持线程安全。并发环境下需要我们自己加锁。且锁的粒度是比较大的。STL极度的追求效率导致内部比较复杂。比如类型萃取迭代器萃取。STL的使用会有代码膨胀的问题比如使用vector/vector/vector这样会生成多份代码当然这是模板语法本身导致的。