一、STL标准模板库简介
STL(Standard Template Library)是C++提供的一组类模板,其中包含容器,迭代器,函数对象和算法。
- 容器(Container):用于保存一组数据的单元;
- 迭代器(Iterator):用于在容器中移动以指向其中的不同数据,可类比于指针;
- 函数对象(Function Objects):作用类似于函数的对象,可以使类对象或函数指针、函数名(函数名起函数指针的作用);
- 算法(Algorithm):用于操作容器中数据的非成员函数。
二、迭代器
可以是对象,也可以是指针。每种STL容器都会提供方法begin() end()返回指向第一个元素和最后一个元素下一个位置的迭代器,可以将end()所指向的位置理解为字符串中的空字符。
语法
vector<double>::iterator pd; vector<double> scores; pd=scores.begin();
如果利用C++11的自动类型推断(automatic type deduction),也可以写成下面的形式:
auto pd=scores.begin();
类型
STL中有物种迭代器,分别为:InputIterator、OutputIterator、ForwardIterator、BidirectionalIterator、RandomIAccessterator。
- 输入迭代器(InputIterator):需要迭代器能够顺序读取容器中所有元素的值,具体来说通过*操作能够访问元素时能读取的值,通过++(前置)和++(后置)能够改变指向的元素。输入迭代器是一种单项迭代器,只能向前移动,同时并不能保证两次遍历同一个容器对象的顺序是相同的。
- 输出迭代器(OutputIterator):与输入迭代器类似,只是用*访问元素的时候不必获得元素的值但需要能够改变元素的值。
- 前驱迭代器(ForwardIterator):只能向前移动迭代器,要求遍历一个容器时每次的顺序一致。
- 双向迭代器(BidirectionalIterator):具有前驱迭代器的所有性质,并要求能够双向移动迭代器,具体来说通过前置和后置的--操作符。
- 随机访问迭代器(RandomAcessIterator):具有双向迭代器的所有性质,并要求能随机访问元素和重载关系运算符。
事实上,以上迭代器之间是一种继承的关系。
为什么需要不同种类的迭代器?
为了让算法对迭代器的要求尽可能少。
操作
所有的迭代器都定义了基本的操作符++,*。
用两个迭代器表示一个范围,例如p1,p2是某种容器的迭代器,则[p1,p2)表示的是从p1开始到p2但不包括p2的元素。
三、算法
特点
①使用模板来支持广泛的数据类型;②使用迭代器来操作容器的对象。
这体现的是算法与数据分离的泛型程序设计思想。因为容器可以容纳各种数据类型,而算法与容器分离,因此算法和容器相互独立,在改变或增添容器或算法时,只需改变自身部分。
因为指针本身就是一种迭代器,所以算法也可以运用于内置数组。
算法分类
STL将算法分成以下几类:
- 非修改性序列操作(Nonmodifying Sequence Operation ):如find(),for_each()。
- 修改性序列操作(Mutating Sequence Operation):如transform(),random_shuffle(),copy()。
- 排序和关系操作(Sorting and Relation Operation):如sort()。
- 通用数字操作(Generalized Numeric Operation):如计算部分和,相邻元素之差的算法。
前三类在头文件algorithm中描述,第四种在头文件numeric中描述。
算法属性
从算法的操作结果去向来看可以分成两种:
- 就地算法(in-place algorithm):在输入容器中操作而不返回,如sort();
- 复制算法(copying algorithm):不改变输入参数,将操作结果保存至输出容器中并返回一个迭代器,该迭代器指向复制的最后一个值的下一个位置,如copy()。
但是有些算法可以可以同时改变输入容器并返回改变的结果。
在就地算法名后加上_copy可以使用对应的复制算法版本,例如:
template <class ForwardIterator, class T> void place (ForwardIterator first, ForwardIterator last, const T & old_value, const T & new_value);
是就地算法,而
template <class InputIterator ,class OutputIterator, class T> OutputIterator replace_copy(InputIterator first, InputIterator last, OutputIterator result, const T & old_value, const T & new_value);
则是复制算法,结果会被复制到result中。
另外若在就地函数后面加入_if则根据条件判断是非复制,例如:
template <class ForwardIterator, class Predicate, class T> void place (ForwardIterator first, ForwardIterator last, Predicate pred, const T & old_value, const T & new_value);
若函数应用于old_value的结果是true,则进行复制。
算法举例
1、for_each():对容器中指定范围的元素(由前两个参数确定)进行操作(由第三个参数函数对象确定);
2、random_shuffle():对容器内指定范围的元素进行随机排列,要求容器支持随机访问。