STL具有容器概念和容器类型。概念是具有名称(比如容器、序列容器、无序容器之类的)的通用类别;容器类型是可用于创建具体容器对象的模板。之前的容器类型有:deque、list、queue、priority_queue、stack、vector、map、multimap、set、multiset、bitset(最后一个是在比特级处理数据的容器)
在C++11标准下又添加了如下容器:forward_list、unordered_map、unordered_multimap、unordered_set、unordered_multiset
容器概念
容器是存储在其他对象的对象,被存储的对象必须是同一类型的,可以是内置类型,也可以是OOP意义上的对象,存储在容器中的对象为容器所有,因此当容器过期时,存储在其中的对象也会过期,但是如果存储的对象是指针,它指向的数据不一定会过期,但是之前说过智能指针又是一种情况。存储的对象类型必须是可复制构造和可赋值的,要求类定义不将复制构造函数和赋值运算符设置为私有或保护。C++11改进了这些概念,添加了术语:可复制插入和可移动插入。
基本容器不能保证其元素顺序都按照特定的顺序存储,也不能保证元素的顺序不变,对概念进行改进后,可以添加这样的保证。
下面是一些基本容器的特征:
C:容器种类
T:容器中数据类型
I:迭代器
id:容器名称
表达式 | 返回类型 | 描述 | 时间复杂度 |
C::value_type | T | 返回容器中存储数据的数据类型 | 编译 (即在编译阶段就完成了这个操作) |
C::iterator | I | 返回指向对应容器的迭代器 (满足正向迭代器所有要求) | 编译 |
C id; | 创建一个为对应容器类型名称为标识符的容器 | 固定 (运行时执行,时间固定) | |
C (); | 创建一个匿名容器 | 固定 | |
C id1(id2); | 调用复制构造函数将容器id2赋值给id1 | 线性 (与元素数目有关) | |
C id1=id2; | 同上一个 | 线性 | |
C& id2 =id1 | C& | 即创建一个容器的引用 | 线性 |
(&id)->~C() | void | 对容器中每个元素应用析构函数 | 线性 |
id.begin() | I | 返回指向容器第一个元素的迭代器 | 固定 |
id.end() | I | 返回容器的超尾迭代器 | 固定 |
id.size() | 无符号整型 | 返回容器中元素的数目,等价于a.end()-a.begin() | 固定 |
id1==id2 | bool | 判断两个容器是否相等,如果两个容器长度相同并且id1中每个元素都等于对应的id2中的元素,那么返回为真,否则为假 | 线性 |
id1!=id2 | bool | 判断不等于 | 线性 |
C++11新增容器要求
rv:对应容器类型的非常量右值
在上表中要求C::iterator满足正向迭代器要求,而之前只需要它不是输出迭代器
表达式 | 返回类型 | 描述 | 时间复杂度 |
C id(rv); | 使用移动构造函数令u的值与rv的原始值相同 | 线性 | |
C id=rv; | 同上 | 线性 | |
id=rv | C& | 使用移动赋值运算符令id的值与rv的初始值相同 | 线性 |
a.cbegin() | const_iterator | 返回一个对应的const迭代器 | 固定 |
a.cend() | const_iterator | 返回一个对应的const迭代器 | 固定 |
下面是对于上面一些特征的应用: