简单来说存入顺序和取出顺序一致的容器被称为顺序容器.
9.1顺序容器概述
vector和string将元素保存在连续的内存空间中,所以每次添加或删除元素都会非常耗时,但是通过下标计算内存地址来读取元素是非常快的.
list和forward_list为链表,添加或删除元素的操作很快,但是不支持元素的随机访问,为了访问一个元素,可能需要从头开始遍历整个容器..
deque和vector,string一样支持快速随机访问,
forward_list和array是C++新标准增加的类型.
array和数组使用上基本一致,但比原生的数组更安全,更容易使用(书上这么说).
C++中推荐使用标准库容器,而不是原始的数据结构.
一般情况下,没有更好的理由的时候,推荐使用vector.
9.2容器库概览
9.2.1迭代器
迭代器是可以通过解引用*来获取指向的元素值.通过容器的begin和end获取到的迭代器为迭代器范围,是左闭右开区间:[begin,end).(解引用容器的begin可以得到容器的第一个元素,解引用容器的end()-1,可以得到容器的最后一个元素,)
另外,上例迭代器的类型是vector<int>::iterator;记不住就写auto.
9.2.2容器类型成员
没啥可说的
9.2.3 begin和end成员
begin和end有多种版本,开头带r的是反向迭代器,加c的是返回const迭代器,当不需要通过迭代器修改元素时,推荐使用cbegin和cend.
9.2.4容器定义和初始化
当一个容器初始化为另一个容器的拷贝时,两个容器的容器类型和元素类型必须相同.
初定义一个array时除了元素类型,还需要指定容器大小,因为大小也是类型的一部分:
array<int,10> a; //大小为10,元素类型为int的array容器
array和内置数组不同的是,内置数组不能进行拷贝或对象赋值操作,但array可以.
9.2.5 赋值和swap
swap交换后,元素本身未交换,swap只是交换了两个容器的内部数据结构,由于元素不会被移动,那么swap可以在常数的时间内完成(快).
我们可以从上面的例子中看出交换前后,同一个地址的元素并没有发生改变.
但是如果swap的是两个array,那么两个arrary会真正地交换它们的元素.
9.2.6容器大小操作
成员函数size返回容器中元素的数目.empty返回容器是否为空.max_size返回一个大于或等于该类型容器所能容纳的最大的元素数.capacity返回容器的容量.
容器容量>=容器元素数目.
9.2.7关系运算符
每个容器类型都支持==和!=的比较,会对两个容器进行逐元素对比.
只有当容器元素类型定义了相应的比较运算符(<,>,<=,>=)时,才可以使用关系运算符来比较两个容器.
9.3顺序容器操作
9.3.1向顺序容器添加元素
在vector或string的尾部之外的任何位置或是deque的首位之外的位置添加元素,都需要移动元素.并且可能会引起vector和string整个对象存储空间的重新分配.
本章建议去力扣找几道题目去刷一下,熟悉熟悉C++的容器以及对应的操作方法.
9.3.2访问元素
下标越界是很严重的错误,然而编译器不检测这样的错误.
使用at成员函数访问元素可以检测出下标越界错误.
9.3.3删除元素
和其他语言不同的是,C++的pop不会把删除的元素返回,而是返回void,如果需要弹出的值,那么需要提前保存下来.
9.3.4 特殊的forward_list操作
9.3.5改变容器大小
9.3.6容器操作可能使迭代器失效
因为容器操作可能导致容器的存储地址改变.
不要保存end返回的迭代器!
9.4 vector对象是如何增长的
为了减少因为改变容器内容而重新分配内存地址的次数,vector通常会保留比size更大的地方,来避免每次添加元素都要重新分配内存地址,这就是为什么之前说容量>=大小的原因.
容器的size是指容器已有的元素数目.容器的capacity是指在不分配新的内存空间的前提下可以保存多少元素.
可以调用shrink_to_fit来要求vector将超出当前大小的多余内存退还给系统.
然后shrink_to_fit只是请求,并不保证标准库一定会退还内存.
9.5额外的string操作
9.5.1构造string的方法
9.5.2改变string的其他方法
9.5.3string搜索操作
9.5.4 compare函数
9.5.5数值转换
9.6容器适配器
标准库定义了三种顺序容器适配器:statck(栈),queue(队列),priority_queue.
适配器是标准库中的通用概念,本质上适配器是一种机制,使得某种事物的行为看起来像另一种事物.