C++ STL总结(一)
通用容器的分类
STL 对定义的通用容器分三类:顺序性容器,关联式容器和容器适配器。
顺序性容器:是一种各元素之间有顺序关系的线性表,是一种线性结构的可序群集。顺序性容器中的每个元素均有固定的位置,除非用删除或插入的操作改变这个位置。这个位置和 元素本身无关,而和操作的时间和地点有关,顺序性容器不会根据元素的特点排序而是直接保存了元素操作时的逻辑顺序。比如我们一次性对一个顺序性容器追加三 个元素,这三个元素在容器中的相对位置和追加时的逻辑次序是一致的。
关联式容器:和顺序性容器不一样,关联式容器是非线性的树结构,更准确的说是二叉树结构。各元素之间没有严格的物理上的顺序关系,也就是说元素在容器中并没有保存元素置 入容器时的逻辑顺序。但是关联式容器提供了另一种根据元素特点排序的功能,这样迭代器就能根据元素的特点“顺序地”获取元素。
关联式容器另一个显著的特点是它是以键值的方式来保存数据,就是说它能把关键字和值关联起来保存,而顺序性容器只能保存一种(可以认为它只保存关键字,也可以认为它只保存值)。这在下面具体的容器类中可以说明这一点。
容器适配器:是一个比较抽象的概念, C++的 解释是:适配器是使一事物的行为类似于另一事物的行为的一种机制。容器适配器是让一种已存在的容器类型采用另一种不同的抽象类型的工作方式来实现的一种机 制。其实仅是发生了接口转换。那么你可以把它理解为容器的容器,它实质还是一个容器,只是他不依赖于具体的标准容器类型,可以理解是容器的模版。或者把它 理解为容器的接口,而适配器具体采用哪种容器类型去实现,在定义适配器的时候可以由你决定。
标准容器类 | 特点 |
---|---|
顺序容器类 | |
vector | 可变大小数组。支持快速随机访问。在尾部之外的位置插入或删除元素可能很慢 |
deque | 双端对列。支持快速随机访问。在头尾位置插入/删除速度很快 |
list | 双向链表。只支持双向顺序访问。在list中任何位置进行插入/删除操作速度都很快 |
forward_list | 单向链表。只支持单向顺序访问。在链表任何位置进行插入/删除操作速度都很快 |
array | 固定大小数组。支持快速随机访问。不能添加或删除元素 |
string | 与vector相似的容器,但专门用于保存字符。随机访问快。在尾部插入/删除速度快 |
关联式容器 | |
set | 快速查找,不允许重复值 |
multiset | 快速查找,允许重复值 |
map | 一对多映射,基于关键字快速查找,不允许重复值 |
multimap | 一对多映射,基于关键字快速查找,允许重复值 |
容器适配器 | |
stack | 后进先出 |
queue | 先进先出 |
priority_queue | 最高优先级元素总是第一个出列 |
顺序性容器
概述
除了固定大小的array外,其他容器都提供高效、灵活的内存管理。容器保存元素的策略对容器操作的效率有着固有的,有时是重大的影响。
string和vector将元素保存在连续的内存空间中。由于元素是连续存储的,由元素的下标来计算其他地址是非常快速的。但是,在这两种容器的中间位置添加或者删除元素就会非常耗时:在一次插入或删除操作后,需要移动插入/删除位置之后的所有元素,来保持连续存储。而且,添加一个元素有时可能还需要分配额外的存储空间。在这种情况下,每个元素都必须移动到新的存储空间。
list和forward_list两个容器的设计目的是令容器任何位置的添加和删除操作都很快速。这两个容器都不支持随机访问。另外,与vector、deque、array相比,这两个容器的额外内存开销更大。
deque是一个更为复杂的数据结构。与string、vector类似,deque支持快速的随机访问。与string和vector一样,在deque的中间位置添加或删除元素的代价(可能)很高。但是,在deque的两端添加或删除元素都很快。
forward_list和array是新C++标准增加的类型。与内置数组相比,array是一种更安全、更容易使用的数据类型。与内置数组类似,array对象的大小是固定的。forward_list的设计目标是达到与最好的手写的单向链表数据结构相当的性能。因此,forward_list没有size操作,因为保存或计算其大小就会比手写链表多出额外的开销。
通常,使用vector是最好的选择,除非你有很好的理由选择其他容器
通用容器操作
构造函数
C c; //默认构造函数,构造空容器
C c1(c2); //构造c2的拷贝c1
C c(b, e); //构造c,将迭代器b和e指定的范围内的元素拷贝到c(array不支持)
C c(a, b, c...); //列表初始化c
赋值与swap
c1 = c2
c1 = {a, b, c...}
a.swap(b) //交换a和b的元素
swap(a, b) //与a.swap(b)等价
大小
c.size() //c中元素的数目(不支持forward_list)
c.max_size() //c可保存的最大元素数目
c.empty()
添加/删除元素(不适用于array)
c.insert(args)
c.emplace(inits)
c.erase(args)
c.clear()
获取迭代器
c.begin(), c.end() //返回指向c的首元素和尾元素之后的位置的迭代器
c.cbegin(), c.cend() //返回const_iterator
反向容器的额外成员(不支持forward_list)
reverse_iterator //按逆序寻址元素的迭代器
const_reverse_iterator //不能修改元素的逆序迭代器
c.rbegin(), c.rend() //返回指向c的尾元素和首元素之前位置的迭代器
c.crbegin(), c.crend() //返回const_reverse_iterator
vector && deque && list
vector 是一段连续的内存块,而deque 是多个连续的内存块, list 是所有数据元素分开保存,可以是任何两个元素没有连续。
vector 的查询性能最好,并且在末端增加数据也很好,除非它重新申请内存段;适合高效地随机存储。
list 是一个链表,任何一个元素都可以是不连续的,但它都有两个指向上一元素和下一元素的指针。所以它对插入、删除元素性能是最好的,而查询性能非常差;适合 大量地插入和删除操作而不关心随机存取的需求。
deque 是介于两者之间,它兼顾了数组和链表的优点,它是分块的链表和多个数组的联合。所以它有被list 好的查询性能,有被vector 好的插入、删除性能。 如果你需要随即存取又关心两端数据的插入和删除,那么deque 是最佳之选。

vector
特性
1. 顺序序列
2. 动态数组
3. 能够感知内存分配器的(Allocator-aware)
常用函数
1.构造函数