本章目标
模板
1.了解泛型编程
2.熟悉模板函数
3.熟悉类模板
STL初阶
4.了解什么是STL
5.了解STL版本
6.了解STL六大组件
7.了解如何学习STL
8.了解STL的缺陷
一. 模板
1.1 范型编程
这里要求我们写一个整型的交换函数 对于我们现在来说肯定是伸手就来了是吧
void swap(int& x, int& y) { int tmp = x; x = y; y = tmp; } int main() { int a = 10; int b = 20; swap(a, b); cout << a << endl; cout << b << endl; return 0; }
然后又开始提要求了 现在能不能写一个double类型的交换函数呢?
也很简单是吧 我们只需要将前面的代码复制一遍 然后转化下类型就可以是吧
那么接下来 字符类型呢? 指针类型呢?
他们之间是不是很相似 只需要改变结构数据类型就好了
但是我们每次都要拷贝一遍是不是很麻烦 所以说C++中就引入了一个泛型编程的概念
泛型编程:编写与类型无关的通用代码,是代码复用的一种手段,模板是泛型编程基础
1.2 函数模板
函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。
语法格式如下
我们这里使用typename或者class都是可以的
emplate<typename TP> // template<class TP> void swap(TP& x, TP& y) { TP tmp = x; x = y; y = tmp; } int main() { int a = 10; int b = 20; swap(a, b); cout << a << endl; cout << b << endl; return 0; }
这里不论我们使用整型字符型还是double类型都是可以交换的
那我们可以说 这就是一个函数模板
那么问题来了 我们这两次调用的swap是同一个函数嘛?
很显然不是 因为我们这里连参数都不一样 所以肯定不是一个函数
那么我们调用的函数是从哪里来的呢?
我们在前面是不是说过我们写过的代码其实是一个函数模板啊
所以说我们下面调用的函数实际上是函数模板的实例化
下面介绍下函数模板的一些使用细则
如果前面已经定义了具体类型的参数
如果前面定义了具体类型的参数 那么后面就不会实例化了
我们来看看代码
假如我取消掉int的注释呢?
我们是不是就会发现
可以直接进入汇编代码了 不会出现二义性
这就好比你如果家里做好了饭 是不是就不会出去吃外卖了啊
出现不同不同类型参数
假设我们这里出现一个整型一个字符类型那么这里就会报错了!
为什么呢?
因为这里T一开始推导的是整形 但是后面却又变成字符形了 所以说这里会冲突
这里又两种方式可以解决
一种是类型强转
还有一种就是显示实例化
还有一种方式就是我们多设置一个参数 (类似于函数就可以 )
1.3 类模板
类模板其实和函数模板类似
1.3.1为什么要有类模板
因为在我们实际写代码的过程中 我们使用的变量是会变化的
这个时候用int 下面可能就是用double了
有人可能要问了 我们使用typedef也可以改变啊
那为什么我们不继续使用typedef而使用类模板呢?
因为使用typedef有个致命的缺陷
就是在同一段函数内 我们只能使用一种数据类型
如果typedef是不是整个函数的所有类型都发生变化了啊
所以说这就是我们为什么要使用类模板的原因
1.3.2 类模板的定义格式
类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<>中即可,类模板名字不是真正的类,而实例化的结果才是真正的类.
我们直接来看代码
template<typename T> class Stack//注:此Stack类并不完美,但对于演示来说,Stack是否完美并不重要 { public: Stack(int capacity = 4) { cout << "Stack(int capacity = )" <<capacity<<endl; _a = (T*)malloc(sizeof(T)*capacity); if (_a == nullptr) { perror("malloc fail"); exit(-1); } _top = 0; _capacity = capacity; } void Push(const T& x)//对于这里引用来说,是最好的,因为如果x本身是类,传值就会调用拷贝构造,传引用有效的避免了这种情况 { // .... // 扩容 _a[_top++] = x; } private: T* _a; int _top; int _capacity; }; int main() { Stack<int> st1; st1.Push(1); Stack<double> st2; st2.Push(2.1); return 0; }
我们可以发现 在最后的时候 我们成功使用了两个类型不同的栈 (一个int 一个double)
如果我们不写显示类型的化就会报错
二. 初识STL
2.1 什么是STL?
STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架。
记住STL分别是什么单词就好了
standard 标准
template 模板
libaray 库
2.2 STL的版本
这里有很多个版本 我们需要记住有两个 一个是初始的HP版本 它是由惠普实验室研发的
还有一个就是我们目前研究的版本 SGI版本
原始版本
Alexander Stepanov、Meng Lee 在惠普实验室完成的原始版本,本着开源精神,他们声明允许任何人任意运用、拷贝、修改、传播、商业使用这些代码,无需付费。唯一的条件就是也需要向原始版本一样做开源使用。 HP 版本–所有STL实现版本的始祖。
P. J. 版本
由P. J. Plauger开发,继承自HP版本,被Windows Visual C++采用,不能公开或修改,缺陷:可读性比较低,符号命名比较怪异。
RW版本
由Rouge Wage公司开发,继承自HP版本,被C+ + Builder 采用,不能公开或修改,可读性一般。
SGI版本
由Silicon Graphics Computer Systems,Inc公司开发,继承自HP版 本。被GCC(Linux)采用,可移植性好,可公开、修改甚至贩卖,从命名风格和编程 风格上看,阅读性非常高。我们后面学习STL要阅读部分源代码,主要参考的就是这个版本。
2.3 STL的六大组件
这里我们主要学习的是算法和容器 也即是一些排序交换 和一些基本的数据结构
2.4 如何学习STL
这里借用下 The C++ Standard Library作者的一段话
总结下
我们目前就是要熟练使用STL
再之后了解STL原理 (第一阶段之后)
2.5 STL缺陷
总的来说无非那么几点通病
更新速度慢
追求效率 所以会稍微复杂点
自身有代码膨胀问题(其实就是模板语法导致的
总结
本文简单的介绍了模板的语法还有STL的简单介绍 大家有一个印象就好 我们后面会具体学习
由于作者水平有限 所以错误在所难免 希望大佬看到之后可以及时指正
如果说本文有帮助到你 别忘了 一键三连啊
阿尼亚 哇酷哇酷!