两种模板形式:函数模板、类模板
- 函数模板:
- 目的:使得函数的实现与类型无关
- 格式:
其中,template <class 形参名, class 形参名, ...> 返回类型 函数名(参数列表){函数体 }
- template和class是关键字,class可用typename关键字代替(二者没区别)
- 模板形参:<>中的参数叫模板形参,模板形参有三种:类型形参(由class或typename后接用户自定义形参名构成)、非类型形参(内置类型,如int)、模板形参。编译器由模板自动生成函数时,会用具体的类型名对模板中所有的类型参数进行替换,其他部分则原封不动保留。如下所示:
#include <iostream> using namespace std; template<class T> void Swap(T & x, T & y) {T tmp = x;x = y;y = tmp; } int main() {int n = 1, m = 2;Swap(n, m); //编译器自动生成 void Swap (int &, int &)函数double f = 1.2, g = 2.3;Swap(f, g); //编译器自动生成 void Swap (double &, double &)函数return 0; }
非类型形参与普通函数参数的区别:前者是在编译时确定的,允许将常量值、枚举值、指针等类型作为模板参数传递,并参与模板的实例化和代码生成,从而避免运行时的开销。比如下面的代码,
process<true>()
和process<false>()
的判断完全在编译时完成,二者会生成两种不同的代码逻辑,减轻了运行时的开销;而普通参数是在运行时传递的,即它们的值只有在程序执行时才会确定 。前者可用于生成不同的代码实例,从而提高性能、避免运行时开销template<bool EnableOptimization> void process() {if constexpr (EnableOptimization) {// 在编译时确定是否启用优化std::cout << "Optimization enabled!" << std::endl;} else {std::cout << "Optimization disabled!" << std::endl;} }
- 模板的实例化:编译器根据模板自动生成函数的过程叫模板的实例化,由模板实例化而得到的函数称为模板函数。
- 另一种实例化方法:并非只能通过模板调用语句的实参来实例化模板中的类型参数,也可以使用下述明确指明的方式:
#include <iostream> using namespace std;template <class T> T Inc(int n){return n+1; }int main(){cout << Inc<double>(4) / 2; // 这里致命了实例化的模板函数原型应为:double Inc(double);return 0; }
- 类模板(待续…)
- 格式:
template <class T> class A{ public: T a;T b;T hy(T c, T &d); };
- 格式: