开篇:
为了应付上机考,现在需要总结下关于STL的基础知识。由于以前各种代码都喜欢从头搭起,像这种现成的牛逼的STL就没怎么看,真是作死。现在来突击啦。
开始之前,简单看一段代码,功能很简单,就是要实现对一组数字的排序,以窥STL的一斑。
1 #include "iostream" 2 #include <algorithm> 3 #include <vector> 4 using namespace std; 5 6 int main() 7 { 8 vector<int> score; 9 for(int i=0;i<15;i++) 10 { 11 score.push_back(rand()%100); 12 } 13 vector<int>::iterator bItr=score.begin(); 14 vector<int>::iterator eItr=score.end(); 15 cout<<"\nBefore Sort:\n"; 16 for_each(bItr,eItr,[](int x)->void{cout<<x<<" ";}); 17 cout<<"\nAfter Sort:\n"; 18 sort(bItr,eItr); 19 for_each(bItr,eItr,[](int x)->void{cout<<x<<" ";}); 20 }
以上这段代码简化得蛮极致的吧,采用vector做为数据容器。首先利用for_each()算法,显示数组内容;再调用sort()排序算法,对数组进行排序。然后再使用for_each()算法,完成对排序后数组的展示。
三行关键代码。这就是STL的魅力。这段程序还有一些细节值得注意,这里不展开了。
正文:
言归正传,开始简单介绍下STL。
STL,即Standard Template Library,标准模板库。
(以下摘自百度百科)
STL是由Alexander Stepanov、Meng Lee和David R Musser在惠普实验室工作时所开发出来的。这可能是一个历史上最令人兴奋的工具的最无聊的术语。从根本上说,STL是一些“容器”的集合,这些“容器”有list,vector,set,map等,STL也是算法和其他一些组件的集合。这里的“容器”和算法的集合指的是世界上很多聪明人很多年的杰作。STL的目的是标准化组件,这样就不用重新开发,可以使用现成的组件。
STL被内建在你的编译系统之内。STL的版本很多,常见的有HP STL、PJ STL、 SGI STL等。
STL组成:
包含容器(containers)、迭代器(iterators)、空间配置器(allocator)、适配器(adapters)、算法(algorithms)、仿函数(functors)六个部分。
常用的STL头文件:
(容器部分)<deque>、<vector>、<list>、<map>、<set>、<array>、<forward_list>、<unordered_map>、<unordered_set>、<queue>、<stack>
(迭代器部分)<iterator>、<memory>、<utility>
(适配器)<stack>、<queue>(容器类适配器)
(算法部分)<algorithm>、<functional>、<numeric>
相关概念:
1、容器(Containers)
各种数据结构,如Vector,List,Deque,Set,Map,用来存放数据,STL容器是一种Class Template,就体积而言,这一部分很像冰山载海面的比率。
2、算法(Algorithms)
各种常用算法如Sort,Search,Copy,Erase,从实现的角度来看,STL算法是一种Function Templates。可以认为每个函数在很大程度上都是独立的,其中常用到的功能范围涉及到比较、交换、查找、遍历操作、复制、修改、移除、反转、排序、合并等等。<numeric>体积很小,只包括几个在序列上面进行简单数学运算的模板函数,包括加法和乘法在序列上的一些操作。<functional>中则定义了一些模板类,用以声明函数对象。
3、迭代器(Iterators)
扮演容器与算法之间的胶合剂,是所谓的“泛型指针”,共有五种类型,以及其它衍生变化,从实现的角度来看,迭代器是一种将:Operators*,Operator->,Operator++,Operator--等相关操作予以重载的Class Template。所有STL容器都附带有自己专属的迭代器——是的,只有容器设计者才知道如何遍历自己的元素,原生指针(Native pointer)也是一种迭代器。(补充:软件设计有一个基本原则,所有的问题都可以通过引进一个间接层来简化,这种简化在STL中就是用迭代器来完成的)
4、仿函数(Functors)
行为类似函数,可作为算法的某种策略(Policy),从实现的角度来看,仿函数是一种重载了Operator()的Class 或 Class Template。一般函数指针可视为狭义的仿函数。
仿函数(functors)在C++标准中采用的名称是函数对象(function objects)。仿函数主要用于STL中的算法中,虽然函数指针虽然也可以作为算法的参数,但是函数指针不能满足STL对抽象性的要求,也不能满足软件积木的要求--函数指针无法和STL其他组件搭配,产生更灵活变化。
仿函数本质就是类重载了一个operator()的struct,创建一个行为类似函数的对象。例如下面就是一个仿函数的例子
struct plus{ int operator()(const int& x, const int& y) const { return x + y; } };
然后就可以如下这样使用
int a=1, b=2; cout<<plus(a,b);
5、配接器(适配器)(Adapters)
一种用来修饰容器(Containers)或仿函数(Functors)或迭代器(Iterators)接口的东西,例如:STL提供的Queue和Stack,虽然看似容器,其实只能算是一种容器配接器,因为 它们的底部完全借助Deque,所有操作有底层的Deque供应。(分三种类型)改变Functor接口者,称为Function Adapter;改变Container接口者,称为Container Adapter;改变Iterator接口者,称为Iterator Adapter。配接器的实现技术很难一言蔽之,必须逐一分析。
6、分配器(Allocators)
负责空间配置与管理,从实现的角度来看,配置器是一个实现了动态空间配置、空间管理、空间释放的Class Template。
——参考《STL源码剖析》