STL有六大组件:
- 容器:各种数据结构,用来存放数据,容器分为序列式容器和关联式容器。
- 算法:如sort、search等算法,从实现的角度来看,STL算法是一种function template。
- 迭代器:扮演容器和算法之间的胶合剂,是所谓的泛型指针。
- 仿函数:行为类似函数,可作为算法的某种策略。
- 适配器:一种用来修饰容器和仿函数或迭代器接口的东西,对外提供特定的接口,具有一定规则的数据操作访问。
- 配置器:负责空间配置与管理。
序列式容器
vector
vector的安排和操作方式与array非常相似,两者的唯一区别就是空间的灵活运用。array是静态空间,一旦配置不能更改,如果需要更大的空间的话,需要重新申请内存,再负责原有的数据到新空间。而vector是动态空间,随着元素的加入,他的内部机制会自行扩充空间以容纳新元素。vector实现该机制的主要属性有size和capacity,size记录用户想要申请的空间大小或是vector实际上存储的元素的个数,而capacity记录的是vector实际申请的内存大小,capacity通常大于size,这样当需要向vector加入新元素时,就不需要每次都向系统重新申请内存,提高了数据操作的效率。
vector有对应的迭代器来遍历自己的元素,由于当增加或删除元素时,vector内部有可能会重新分配内存空间,导致迭代器失效,所以在使用vector迭代器的时候,对vector进行元素的增加或删除操作是很危险的。
list
相比较vector,list在任何位置增加或删除元素时,都是常数时间的,但是在随机访问元素时,却比vector差。在STL中,list的实现时以双向环形链表的形式,只需要一个指针,就可以完整表现整个链表。STL会自己增加一个空节点,该结点连接着链表头和尾部节点,从而构成一个环。list.end()就是指向该节点。判断链表是否为空,只需要查看空节点的上一个或下一个节点是否指向自己就好。
list有自己的迭代器,相比于vector,list的插入或删除操作都不会造成原有的迭代器失效,因为list元素的改动不会影响到其他元素的内存位置。当然,删除操作会影响到原来指向被删除的元素的迭代器。
deque
deque是双向开口的,可以在头部或是尾部插入或删除元素。deque与vector的最大差异,一在于deque允许常数时间内对头部进行元素的插入删除操作,二是deque没有capacity观念,因为他是动态的以分段连续的空间组合而成,随时可以增加一段新空间并连接起来。deque采用一块所谓的map作为主控,这里所谓的map是一小块连续空间,其中每个元素都是指针,指向另一段较大的连续线性空间,称为缓冲区,缓冲区才是deque的数据存储空间。
deque也有自己的迭代器。
适配器
stack
stack允许数据先进后出,STL默认采用的是deque容器来作为stack的底层实现。stack封装容器,对外提供特定的数据操作接口,只允许数据先进后出,所以stack没有迭代器。
queue
与stack类似,queue默认采用的也是deque来实现数据的存储,只允许数据先进先出,queue也没有迭代器。
heap
heap并不是STL容器组件,同时priority queue的底层实现算法。二叉堆为完全二叉树,所以可以使用数组来实现heap算法。heap分为max-heap和min-heap。由于堆也规定特定的数据操作规则,所以heap没有迭代器
priority queue
priority queue是一个拥有权值的queue,元素根据权值来排序。默认情况下,priority queue采用max-heap作为底层的实现,而max-heap采用vector作为底层的数据存储结构。priority queue没有自己的迭代器。
关联式容器
标准的STL关联式容器分为set和map两大类,以及这两大类衍生的multiset和multimap。这些都采用红黑树来实现。红黑树是STL的独立容器,不对外开放。
set
set的特点是所有的元素会根据元素的键值自动排序。set的元素不像map那样同时拥有key和value,set元素的key和value是一体的。 因为set的元素值就是其键值,关系到set元素的排列规则,不允许修改set的元素值。set拥有和list相同的某些性质,当客户端进行插入或删除元素时,操作之前的原有迭代器,在操作后都依然有效,当然,被删除的那个元素的迭代器必然是个例外。
map
map的特性是,所有元素会根据key来进行排序,map的所有元素都是pair,同时拥有key和value,因此我们可以根据map的迭代器来修改map的value。map和set一样,在删除或是插入元素时,除了别删除的元素外,其他的迭代器都是有效的。
multiset
multiset的性质和set一样,只不过允许有相同的值。
multimap
multimap的特性与map完全一样,只不过允许有相同的key。
hashtable
hashtable采用字典的形式来存储数据,底层实现为数组加链表。拥有自己的迭代器。