当前课程知识点:C++语言程序设计进阶 > 第十章 泛型程序设计与C++标准模板库 > 泛型程序设计及STL的结构 > STL简介
标准模板库(Standard Template Library,简称STL)提供了一些非常常用的数据结构和算法
标准模板库(Standard Template Library,简称STL)定义了一套概念体系,为泛型程序设计提供了逻辑基础
STL中的各个类模板、函数模板的参数都是用这个体系中的概念来规定的。
使用STL的模板时,类型参数既可以是C++标准库中已有的类型,也可以是自定义的类型——只要这些类型是所要求概念的模型。
容器(container)
迭代器(iterator)
函数对象(function object)
算法(algorithms)
Iterators(迭代器)是算法和容器的桥梁。
将迭代器作为算法的参数、通过迭代器来访问容器而不是把容器直接作为算法的参数。
将函数对象作为算法的参数而不是将函数所执行的运算作为算法的一部分。
使用STL中提供的或自定义的迭代器和函数对象,配合STL的算法,可以组合出各种各样的功能。
容纳、包含一组元素的对象。
基本容器类模板
unorderedset (无序集合)、unorderedmultiset(无序多重集合)
unorderedmap(无序映射)、unordermultimap(无序多重映射)
set(集合)、multiset(多重集合)、map(映射)、multimap(多重映射)
array(数组)、vector(向量)、deque(双端队列)、forward_list(单链表)、list(列表)
顺序容器
(有序)关联容器
无序关联容器
容器适配器
stack(栈)、queue(队列)、priority_queue(优先队列)
使用容器,需要包含对应的头文件
迭代器是泛化的指针,提供了顺序访问容器中每个元素的方法
提供了顺序访问容器中每个元素的方法;
可以使用“++”运算符来获得指向下一个元素的迭代器;
可以使用“*”运算符访问一个迭代器所指向的元素,如果元素类型是类或结构体,还可以使用“->”运算符直接访问该元素的一个成员;
有些迭代器还支持通过“--”运算符获得指向上一个元素的迭代器;
迭代器是泛化的指针:指针也具有同样的特性,因此指针本身就是一种迭代器;
使用独立于STL容器的迭代器,需要包含头文件
一个行为类似函数的对象,对它可以像调用函数一样调用。
函数对象是泛化的函数:任何普通的函数和任何重载了“()” 运算符的类的对象都可以作为函数对象使用
使用STL的函数对象,需要包含头文件
STL包括70多个算法
例如:排序算法,消除算法,计数算法,比较算法,变换算法,置换算法和容器管理等
可以广泛用于不同的对象和内置的数据类型。
使用STL的算法,需要包含头文件
例10-1从标准输入读入几个整数,存入向量容器,输出它们的相反数
transform算法的一种实现:
template <class InputIterator, class OutputIterator, class UnaryFunction> OutputIterator transform(InputIterator first, InputIterator last, OutputIterator result, UnaryFunction op) { for (;first != last; ++first, ++result) *result = op(*first); return result; }
transform算法顺序遍历first和last两个迭代器所指向的元素;
将每个元素的值作为函数对象op的参数;
将op的返回值通过迭代器result顺序输出;
遍历完成后result迭代器指向的是输出的最后一个元素的下一个位置,transform会将该迭代器返回
大家好
欢迎回来继续学习
C++语言程序设计
在这一节
我将STL标准模板库
给大家做一个简要的介绍
在STL库中
有很多有用的数据结构
和算法
标准模板库也就是
standard Template Library
就简称STL
其中定义了一套概念体系
它为泛型设计提供了逻辑基础
STL中的各个类模板
函数模板的参数
都是用这个体系中的概念
来规定的
所以使用STL的模板的时候
类型参数既可以是C++标准库中
已经有的类型
也可以是自己定义的类型
只要这些类型
是所要求的概念的模型就可以了
STL库中有四种基本组件
它们就是容器 迭代器
函数对象和算法
我们来看这张图
它说明了容器 算法
还有函数对象
以及迭代器
它们之间的关系
我们看到从这张图中
也体现出来了
迭代器实际上就是算法
和容器的桥梁
为什么这样说呢
因为为了通用
在STL库中是将迭代器
作为算法的参数的
那么算法通过迭代器来访问容器
而不是说像一般写程序这样
把容器直接作为参数就传给算法
比如说我们写简单程序的时候
可能会将一个数组作为参数
传给一个函数
由这个函数到数组中
去检索一些数据
那这是通常
我们写简单程序的做法
但是STL库里面
为了让这个算法能够尽量通用
能够适用于不同的容器
它就将迭代器作为算法的参数
还有呢
我们算法实现一些功能的时候
比如说实现排序功能的时候
到底是按升序排列
还是按降序排列呢
还有
如果这个排序算法
作用于不同的数据序列
那么不同的数据序列
它比较大小的方式可能不一样
那这个时候
我们怎么能够有一个通用的函数
对什么数据都能够进行排序呢
这个时候我们就要将一些功能
做成可定制的
也就是说
有些算法里面
它有些功能是由函数对象
来定制的
比如说将一个比较大小的函数
传给排序算法
作为函数对象传过去
那么这个排序算法
就可以按照你传过来的这个
比较大小的功能
去实现它的具体的排序功能
这就是将函数对象
作为算法的参数
而不是将函数所执行的运算
作为算法的一部分
这样的话
我们使用STL库中提供的
或者我们自定义的迭代器
和函数对象
再配合STL库里面的算法
就可以组合出各种各样的功能
现在呢
我们再来了解一下
STL库中的一种基本组件 容器
容器就是用来
容纳一组数据元素的对象
容器可以容纳包含一组数据元素
在STL里面
有哪些基本的容器呢
有这样几个容器类模板
一类是顺序容器
比如像数组 向量
双端队列 单链表 列表
还有关联容器
就是有序的关联容器
像集合 多重集合
映射 多重映射
还有一类是无序的关联容器
包括无序集合
无序多重集合
无序映射以及无序多重映射
我们看到
这都是我们常用的数据结构
在库里都事先设计好了
我们拿过来用就行了
它的形式呢
就是类模板的形式
仅仅有这些容器类模板
还不够
我们还需要什么
还需要栈 队列
对吧
那我们在学习第九章的时候
已经知道了
栈和队列实际上
就是存取操作受限制的线性表
那在STL库中也是这样处理的
在基本容器的基础上呢
我们可以附加上适配器
这样就可以构成栈
队列和优先队列了
这就是SLT库里面的容器
适配器 有栈适配器
队列适配器
还有优先队列适配器
当我们要使用容器
和适配器的时候
还需要包含相应的头文件才可以
STL库里面的
另一个有用的基本组件
就是迭代器
迭代器是什么呢
迭代器就是一个泛型的指针
它可以用来顺序访问
容器中的各个元素
说迭代器是一个泛型的指针
那么它有指针那么好用吗
它比指针更好用
仅仅使用迭代器
我们就可以顺序访问
容器中的每个元素
因为迭代器附有访问元素的方法
在迭代器上呢
我们可以使用自增运算符
也就是++运算符
来获取指向下一个元素的迭代器
也就是使迭代器
向前走一个元素
还可以使用指针运算符
通过迭代器访问它所指向的元素
如果
它指向的元素类型是类
或者结构体
那么我们还可以用
这种指向运算符
就是减号 大于号构成的
这个指向的这样的运算符
直接访问这个元素的成员
有些迭代器呢
还可以支持这个自减运算
通过支持自减运算呢
获得指向上一个元素的迭代器
也就是
让这个迭代器在遍历过程中
回退一个元素
我们说迭代器
是泛化的指针
实际上指针呢
它也具有同样的特性
所以其实指针
本身就是一种迭代器
在STL库的容器
都可以返回指向自身元素
用于遍历自身元素的迭代器
如果我们要使用独立于
STL容器的迭代器呢
就要包含头文件itrator
函数对象呢
也是STL库里面
一个非常有用的组件
什么是函数对象呢
就是一个行为类似于函数的对象
我们可以像调用函数一样
去使用这个对象
函数对象呢
实际上就是泛化的函数
任何普通的函数
和任何重载了
函数调用运算符的类的对象
都可以作为函数对象来使用
如果我们要使用STL库里面
给我们提供的函数对象
我们就需要包含头文件function
STL库中
为我们提供了70多个
非常有用的算法
可以广泛应用于内置类型
和对象类型
比如说排序算法 消除算法
计数算法 比较算法 变换算法
置换算法
和容器管理等等
都是非常常用的算法
我们要使用STL的算法呢
就需要包含头文件algorithm
下面这个例题呢
从标准输入设备
也就是键盘
读入一系列的整数
然后把它们存在向量中
最后输出它们的相反数
我们来看看
在这里我们怎么使用容器的
在这个程序中我们用到了容器
算法 迭代器
和函数对象
首先我们构造
vector int的一个对象s
这是一个容器
需要它容纳五个元素
接下来呢
从键盘输入这五个元素
存放到s这个容器中
然后使用transform这个算法
使用这个算法
我们需要将容器中的这几个元素
依次取它的相反数
然后输出
在transform里面
我们给出了这样三个迭代器
s.begin s.end
是指向我们要处理的数据的
开头和结尾的位置
所以呢
有了这两个迭代器
transform算法
就可以依次处理
从begin到end的这些元素
然后处理的结果呢
会按照这个输出流迭代器
指示的位置
去依次送到输出流里面去
这里给的
输出流迭代器的这个参数
是cout
所以就会输出到标准输出设备
通常这个显示器里面
那么处理的时候
处理每个元素的时候
用什么方法呢
这里给出了函数对象
这个函数对象
就是用于求相反数的
所以经过这个
transform算法的执行呢
就将容器s中的对象
从begin到end的位置
各个依次求相反数
并且依次送到
这个标准输出流中去了
我们在刚才的例题中看到了
一个transform算法
那么这个算法
它的实现原理到底是什么呢
这里给出了
transform算法的一种典型的实现
我们看这个函数体中
实际上就是通过一个循环
遍历整个数据序列
在遍历的过程中呢
使用函数对象op
对元素进行处理
每一个元素都要用函数对象op
进行处理
那么op的返回值呢
也就是处理结果
放到哪儿去呢
通过result这个迭代器进行输出
进行顺序输出
这样经过这样一轮遍历以后呢
result迭代器指向的位置
就是输出的最后一个元素的
下一个位置
最后transform算法
会将result这个迭代器
作为返回值返回
-导学
--导学
-继承的基本概念和语法
-第七章 继承与派生--继承的基本概念和语法习题
-继承方式
-第七章 继承与派生--继承方式
-基类与派生类类型转换
-第七章 继承与派生--基类与派生类类型转换
-派生类的构造和析构
--派生类的构造函数
--派生类的析构函数
--第七章 继承与派生--派生类的构造和析构
-派生类成员的标识与访问
--虚基类
-第七章 继承与派生--派生类成员的标识与访问
-小结
--小结
-综合实例
--第七章综合实例
-实验七
--实验七
-导学
--导学
-第八章 多态性--导学
-运算符重载
--运算符重载的规则
-第八章 多态性--运算符重载
-虚函数
--虚函数
--虚析构函数
--虚表与动态绑定
-第八章 多态性--虚函数
-抽象类
--抽象类
--第八章 多态性--抽象类
-override与final
-第八章 多态性--override与final
-小结
--第八章小结
-综合实例
--第八章综合实例
-实验八
--实验八
- 第八章讲义
-导学
--导学
-模板
--函数模板
--类模板
-第九章 模板与群体数据--模板
-线性群体
--线性群体的概念
-第九章 模板与群体数据--线性群体
-数组
--数组类模板
-链表
--链表类模板
-第九章 模板与群体数据--链表
-栈
--栈类模板
--栈类模板课后习题
--例9-9 栈的应用课后习题
-队列
--队列类模板
-第九章 模板与群体数据--队列
-排序
--排序概述
--插入排序
--选择排序
--交换排序
-第九章 模板与群体数据--排序
-查找
--查找
--查找课后习题
-小结
--小结
-综合实例
--综合实例
-实验九
--实验九
- 第九章讲义
-导学
--导学
-泛型程序设计及STL的结构
--STL简介
-第十章 泛型程序设计与C++标准模板库--泛型程序设计及STL的结构
-迭代器
--迭代器
-第十章 泛型程序设计与C++标准模板库--迭代器
-容器的基本功能与分类
-第十章 泛型程序设计与C++标准模板库--容器的基本功能与分类
-顺序容器
--顺序容器的特征
--第十章 泛型程序设计与C++标准模板库--顺序容器
-关联容器
--集合
--映射
-第十章 泛型程序设计与C++标准模板库--关联容器
-函数对象
--函数对象
--函数适配器
-算法
--算法
-小结
--第十章小结
-综合实例
--综合实例
-实验十
--实验十
- 第十章讲义
-导学
--导学
-I/O流的概念及流类库结构
-第十一章 流类库与输入/输出--I/O流的概念及流类库结构
-输出流
--输出流概述
--向文本文件输出
--向二进制文件输出
--向字符串输出
-第十一章 流类库与输入/输出--输出流
-输入流
--输入流概述
--输入流应用举例
--从字符串输入
-第十一章 流类库与输入/输出--输入流
-输入/输出流
--输入/输出流
-第十一章 流类库与输入/输出--输入/输出流
-小结
--小结
-综合实例
--综合实例
-实验十一
--实验十一
- 第十一章讲义
-导学
--第12章导学
-异常处理的思想与程序实现
-第十二章 异常处理--异常处理的思想与程序实现
-异常处理中的构造与析构
-第十二章 异常处理--异常处理中的构造与析构
-标准程序库异常处理
-第十二章 异常处理--标准程序库异常处理
-小结
--第12章小结
-综合实例
--综合实例
-实验十二
--实验十二
- 第十二章讲义