从根本上说,STL是一些“容器”的集合,这些“容器”有list,vector,set,map等,STL也是算法和其他一些组件的集合。这里的“容器”和算法的集合指的是世界上很多聪明人很多年的杰作。STL的目的是标准化组件,这样就不用重新开发,可以使用现成的组件。STL现在是C++的一部分,因此不用安装额外的库文件。
在C++标准中,STL被组织为下面的17个头文件:<algorithm>、<deque>、<functional>、<iterator>、<array>、<vector>、<list>、<forward_list>、<map>、<unordered_map>、<memory>、<numeric>、<queue>、<set>、<unordered_set>、<stack>和<utility>。再分细一点:STL可分为容器(containers)、迭代器(iterators)、空间配置器(allocator)、配接器(adapters)、算法(algorithms)、仿函数(functors)六个部分。
上面都是百科大家都能看到的东西,是精准的概括。
STL有一个很重要的特点,就是STL是基于模板的,而不是面向对象的,也就是说不基于封装、多态(C++中真正的多态是虚函数)、继承这面向对象编程的三个要素。就是因为没有类继承这一说法,所以,STL组件恰恰具有广泛通用性的底层特征,举个例子,STL中提供了大概50种算法,这些算法完全都是通用的,不依赖于任何特定数据类型,这就是STL:标准、通用、底层。而且STL又提供了大量的模板类和函数,也能在面向对象编程中广泛应用。
STL的三个基本组件:
1.迭代器,在《C++程序语言设计》本书中,很直白:迭代器就是泛化的指针。STL算法利用迭代器对存储在容器中的元素序列进行遍历,迭代器提供了访问容器中每个元素的方法。指针是一种迭代器,但是迭代器却不仅仅是指针,区别如下:指针可以指向内存中的一个地址,通过这个地址就可以访问相应的内存单元,而迭代器更为抽象,它可以指向容器中的任何一个位置,任何的它的容器,不管这个位置对应的真正的物理地址,反正,通过迭代器能访问这个位置的元素。迭代器,就是算法和容器的“中间人”。
2.容器,STL里总共有7种容器,分别是
vector 向量 <vector> 随机访问容器,顺序容器
deque 双端队列 <deque> 随机访问容器,顺序容器
list 列表 <list> 可逆容器,顺序容器
set 集合 <set> 可逆容器,关联容器
multiset 多重集合 <set> 可逆容器,关联容器
map 映射 <map> 可逆容器,关联容器
multimap 多重映射 <multimap> 可逆容器,关联容器
,每种都有不尽相同的功能和用法。主要是顺序容器和关联容器两个子概念(基于元素组织方式),或者说是容器->可逆容器->随机访问容器(按照关联迭代器划分)
一般容器的begin()和end()成员函数所得到的迭代器都是前向迭代器,是对容器元素的单向遍历;
而可逆容器所提供的迭代器都是双向迭代器,可以对元素进行双向的遍历,成员函数多了rbegin()和rend(),逆向的;
更进一步的随机访问容器,就对应随机访问迭代器了,支持对元素进行随机访问,设整数n可以指定访问,比如s1[n],获得容器的第n个元素,其实就是等同于s1.begin()[n]。
3.算法<algorithm>:标准C++算法是通过迭代器和模板来实现的,算法其实本身就是一种函数模板,算法要获得一个数,必须要迭代器先知道这个元素是在容器中的什么位置,迭代器在容器里找到之后,把元素的位置等信息提供给算法,这样以来算法才能快速访问这些元素。算法本身不用关心这个元素是什么数据类型,存储在容器哪个地方,它只管拿到即可,随意一个标准的C++算法,就可以处理几乎所有类型的容器,别忘了,随便一个容器,在STL里,不管什么数据类型的元素,都能放进去,也就是说,算法这种通用性,非常强大。
分类中大概是4类算法:
(1)不可变序列算法:不直接修改所操作的容器内容,举几个典型的例子,后面的三种算法都举典型的例子
count(计数)、find(循环查找)、equal(判断两个区间是否相等)、search(查找某个子序列)
(2)可变序列算法:修改他们所操作的容器内的元素
copy(复制区间所有元素)、generate(连续调用函数对象,计算区间中元素的函数值,然后依次替换掉区间中的相应元素)、fill(用某一数值替换区间中的所有元素)、remove(删除区间中所有等于某数值的元素)、replace(替换某类元素)、reverse(反转区间元素次序)、swap(交换元素)、unique(查找并删除区间内连续相等的元素,使之成为唯一)、random_shuffle(随机重排区间元素)
(3)排序和搜索算法:这一类的算法,都是通过对序列元素进行对比操作来完成的。
其中有四个排序算法:sort,partial_sort,parial_sort_copy,stable_sort
四个二分搜索算法:binary_search,lower_bound,uper_bound,equal_range
两个合并有序区间的通用算法:merge,inplace_merge
四个最值算法:max,min,min_element,max_element
此外还有三个与排列方式有关的算法,五个用于有序序列上的集合操作(includes、set)的算法以及四个为堆(heap)的创建和操作提供的算法。
(4)数值算法:STL提供了4个通用数值算法,都必须要引用头文件<numeric>
分别是: accumulate 计算序列中所有元素的和
partial_sum 累加序列中部分元素的值,并将结果保存在另一个序列中
adjacent_difference 计算序列中相邻元素的差,并将结果保存在另一个容器中
inner_product 累加两个序列对应元素的成绩,也就是序列的内积
以上,就大概介绍了STL的构成,当然并不全面而且详细,C++标准库之所以能提供更安全和灵活的数据集处理方式,就是得益于STL的几个特点:
数据结构和算法分离,非面向对象本质。
访问对象是通过迭代器(比如指针)来实现的。
容器是像链表、矢量之类的数据结构,并按模板方式提供的。
算法就是函数模板,来操作容器里的各种数据。
所以,STL,能用于任何的数据类型和结构。