- 顺序容器包括 vector, string, deque, list, forward_list, array.
- vector 是应用最广泛的,元素顺序存储。
- string和vector类似,但是存储字符串
- deque为双向列表。可以从前后来进行插入和删除
- list为双向链表。从任何位置插入删除的速度都很快。但是非顺序访问的速度比较慢。(这也是所有链表的特征)
- forward_list 为单向链表,特征和list差不多
- array为定长数组,可以替代内置类型的数组。更加安全。应该要替代。
- 顺序容器的特征:元素存储的先后顺序是根据其存储位置来确定的。
- 顺序容器的操作:
可以分为 容器都有的操作,顺序容器和关联容器都有的操作,顺序容器独有的操作,关联容器独有的操作。
有层次关系的。容器都有的操作
-
总述:
- 一些类型别名。比如 iterator, const_iterator, value_type 等
- 构造函数:默认构造函数,拷贝构造函数,使用另外一个容器的iterator指针的构造函数(此时不要求iterator指向的类型和被赋值的类型相同。比如,一个map的元素可以进行赋值给一个vector,只要元素类型相同或者可以转换即可),列表初始化构造
- 可以使用 = 进行赋值,等号右边可以是另外一个相同元素或者一个{}列表
- swap(a, b) a.swap(b) 可以调换两个中的内容。
- 大小相关: c.size() 返回大小,
-
容器的迭代器
迭代器的范围往往是左闭右开的。之所以这样,是因为方便表示集合为空(begin和end相等)。否则不好表示
迭代器一般都定义了++,–操作(forward_list没有定义–) -
容器定义和初始化
- 容器的构造函数除了上述的,对于顺序容器(除了array),还可以使用 C c(n), n表示个数。C c(n, v) n表示个数,v表示初始化的值
- array类型必须指定元素类型和大小。因此,不适用于有些构造函数。其再创建之初就分配了空间。没有指定值的话,就进行默认值初始化。array不支持使用迭代器指针的构造函数,1中所说构造函数。不支持=右边为{}的赋值。其余的操作支持。
- 顺序容器(除了array)支持和 = 类似作用的操作 assign,可以将不同的内容赋值给调用的容器对象。
- 交换操作:swap 函数。除了array,其他的swap都不会对真正的数据内容进行交换,而是会改变名字和内容之间的对应关系。string在swap之后迭代器会失效。
顺序容器特有的操作
-
插入操作:
- push_back :除了array和forward_list都提供
- push_front : 仅仅list,deque,forward_list 提供了
- insert: 可以实现在任何位置加入 0个或者多个元素。有四种形式,insert(p, begin,end) insert(p, v) insert(p, n, v) insert(p, {初始化列表})除了array和forward_list之外的顺序容器成员具备。往往返回新添加的第一个元素的迭代器。因此可以利用这个返回值来进行多次的循环插入。
- emplace_back,emplace_front,emplace 是新标准引入的,可以替代前面几个的新函数。其参数是容器元素类型的构造函数的列表,直接调用构造函数。而不是像push和insert的那样调用元素的拷贝构造函数。
-
访问元素
- front和back(forward_list不支持)可以返回一个容器的首尾元素的引用。 是可以进行赋值,然后改变其容器中的值的。如果将其赋值给一个非引用的类型,那么相当于值的拷贝。如果赋给一个引用,则可以进行修改。
- 可以通过 下标运算符来操作(支持随机访问的顺序容器才适配,string vector deque array)。和下标运算符类似的还有at函数,参数为下标。at函数更加安全,因为当其越界的时候,是抛出异常,而不是直接运行时错误。
-
删除元素(非array)
- pop_back() forward_list不支持
- pop_front() vector string不支持
- erase ( p) earse(b, e) 返回被删或者最后被删元素的后一个元素的迭代器。其中 b e的关系为 [b, e)
- clear() 清除所有元素
-
forward_list 操作
- 因为其为单向的,因此插入和删除不可以通过常规的方法来操作。其定义了 insert_after, emplace_after erase_after之类的函数。
- 其有before_begin()表示第一个元素之前的没有定义的头节点。有时候可以用来进行一些方便的操作。因为在对其进行操作的时候,想要删除一个元素,需要知道这个元素之前的迭代器。
- 容器操作 插入,删除之类的,很可能导致原来的迭代器失效。但是具体问题具体分析。list和forward_list 因为是链表结构,在删除之后,迭代器一般不会失效。
-
- vector对象是如何增长的
- vector如果需要重新分配空间的话,将会非常麻烦。需要申请空间–> 复制原来元素–> 添加新的元素 --> 释放旧空间。因此,vector往往会有预留空间。
- c.capacity() 表示不重新分配内存的话,当前可以容纳多少个元素。reserve(n) 表示分配至少n个元素的空间。reserve参数如果大于当前的需求的话,会分配到可以容纳 >= n 个元素的空间。如果小于当前需求,也不会缩水。
- c.shrink_to_fit() 为建议缩小到够放就行 size()大小。但是有时候不会照做。
- 额外的string操作
- string的额外的构造函数:
- 可以使用一个字符数组来作为参数拷贝。会将其字符一个个拿过来,到碰到’\0’为止。一般的char* 字符串是有\0 的(只用 ”str“形式来进行初始化),但是有些char[] 字符串如果采用 {} 初始化的话(使用"str"来初始化的有),没有加’\0’。那么就会出现错误。
- string s(cp, n) 拷贝前n个字符
- string s(s1, pos) s1的pos之后(包括pos)之后的字符串
- string s(s1, pos, len) 的pos之后的len个
- substr用于截取子串。开始位置只要不超过结尾下表就可以了。
- string定义了insert和erase的下标版本。
- string定义了append,replace。append其实就是insert到末尾的简写。和push_back类似。replace其实就是erase和insert的简写。会先进行删除,然后进行插入。
- string搜索操作:
- find函数(用来查找第一个符合这个字符串的index),rfind()
- find_first_of(字符或者字符集合成的字符串) 查找第一次出现参数中某一个字符的位置 find_last_of
- find_first_not_of () find_last_not_of()
- compare操作 和strcmp类似,返回0 正数 或者 负数
- 数值转换:to_string()可以将数值转换为string。 stod stoi 等等函数可以将string转化为对应的数值。对应的string可以是十进制或者其他进制,可以包含e 或者 E。
- string的额外的构造函数:
- 容器适配器
- 包括stack,queue, priority_queue.
- 适配器其实就是在容器的基础上进行适配,使其行为像是另外一个东西。stack,queue就是适配的结果。
- 栈和queue默认基于deque实现。也可以基于其他容器实现。如果需要改变适配,作为第二个类型参数传入。