【C++】模版初阶以及STL的简介
个人主页~
模版及STL
- 一、模版初阶
- 1、泛型编程
- 2、函数模版
- (1)概念
- (2)函数模版格式
- (3)函数模版的原理
- (4)函数模版的实例化
- ①显式实例化
- ②隐式实例化
- (5)模版参数的匹配原则
- 3、类模版
- (1)类模板的定义格式
- (2)类模板的实例化以及类函数的使用
- 二、STL简介
一、模版初阶
1、泛型编程
我们在先前的博文中提到过函数重载交换函数swap,但是使用函数重载有几个不好的地方:
1、重载的函数仅仅是类型不同,代码复用率比较低,所有的重载函数中只有数据类型不同,其他的都基本相同, 只要有新类型出现就需要用户自己增加对应的函数
2、代码可维护性低,其中某一函数出错可能会导致所有重载都出错
解决这个问题的方法就是有一个模具,只要相同的就直接套用,不同的替换就可以了
泛型编程就是编写与类型无关的通用代码,是代码复用的一种手段,模版是泛型编程的基础
2、函数模版
(1)概念
函数模版代表了一个函数家族,该函数模版与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本
(2)函数模版格式
template type name () {}
template就是一个函数模版关键字后跟,参数放里边
typename是一个类类型参数,也可以写成class,但不能写成struct,它代表name函数可以操作的数据类型。当调用name函数时,编译器会根据传递给函数的实参类型来推断T的具体类型
type name(){}就是一个函数
具体看这个例子:
template void Swap( T& left, T& right) { T temp = left; left = right; right = temp; }
(3)函数模版的原理
模版是编译器用使用方式产生特定具体类型函数的模具,它本身并不是函数,所以模版就是将本来应该由我们做的重复的事情交给了编译器
在编译器的编译阶段,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用,将T确定为某一具体类型,然后产生一份专门处理该类型的代码
(4)函数模版的实例化
用不同类型的参数使用函数模版时,称为函数模版的实例化,分为显式实例化和隐式实例化
①显式实例化
template T Add(const T& left, const T& right) { return left + right; } int main() { int a = 10; double b = 20.0; // 显式实例化 Add(a, b); return 0; }
格式:函数名+(参数)
②隐式实例化
template T Add(const T& left, const T& right) { return left + right; } int main() { int a1 = 10, a2 = 20; double d1 = 10.0, d2 = 20.0; Add(a1, a2);//意味着T实例化为int Add(d1, d2);//意味着T实例化为double return 0; }
这是当两个参数类型相同的时候,如果两参数类型不同该语句不能通过编译,因为在编译期间,当编译器看到该实例化时,需要推演其实参类型,通过实参a1将T推演为int,通过实参d1将T推演为double类型,但模板参数列表中只有一个T,编译器无法确定此处到底该将T确定为int 或者 double类型而报错,所以我们要进行手动强制类型转换
注意:在模板中,编译器一般不会进行类型转换操作
(5)模版参数的匹配原则
①一个非模版函数可以和一个同名的函数模版同时存在,而且该函数模版还可以被实例化为这个非模版函数
int Add(int left, int right) { return left + right; } template T Add(const T& left, const T& right) { return left + right; } int main() { cout Add(1, 2);//非模版更匹配,会直接选择非模版函数,不必再特化 Add(1, 2.0);//模版生成的函数比非模版函数更加匹配,这样就会选择模版 return 0; } // 类内成员定义 }; public: Vector(size_t capacity = 10) : _pData(new T[capacity]) , _size(0) , _capacity(capacity) {} //模版外定义函数 ~Vector(); void PushBack(const T& data); //模版内定义函数 void PopBack() { _size--; } size_t Size() { return _size; } private: T* _pData; size_t _size; size_t _capacity; }; // 类模板中函数放在类外进行定义时,需要加模板参数列表 template if (_pData) delete[] _pData; _size = _capacity = 0; } //每次函数定义都要加模版参数列表 template if (_size == _capacity) { size_t newcapacity = _capacity * 2; T* ptr = new T[newcapacity]; for (int i = 0; i