容器分类
顺序容器包括以下几种:
- vector 可变大小的数组;
- deque 双端队列;
- list 双向链表;
- forwart_list 单向链表;
- array 固定大小数组;
- string 专门保存char的容器;
相对原生数据结构而言,容器在内存和性能方面都有诸多益处;所以尽量使用标准库里面的容器;
以上几种容器类型的特点:
类型 | 迭代器类型 | 插入和删除元素 | 包含头文件 | 选择参考 |
---|---|---|---|---|
vector | 随机存取迭代器 | 尾端高效 | < vector> | 动态大小,随机访问 |
deque | 随机存取迭代器 | 首尾高效 | < deque> | 两端需要操作 |
list | 双向迭代器 | 均高效 | < list> | 中间操作 |
forward_list | 前向迭代器 | 均高效 | < forward_list> | 中间操作 |
array | 随机存取迭代器 | —- | 无插入和删除操作 |
注意:
1. 尾端高效意味着 其他位置插入和删除比较低效;
2. —-意味着 不支持插入和删除;
3. 均高效 意味着在知道指定位置上插入高效;
容器操作
每种容器里面都含有这几个基本内置类型,在介绍容器操作的时候
- iterator/const_iterator 迭代器类型
- size_type 无符号整数类型,与容器的大小相同单位
- difference_type 带符号整数,保存两个迭代器之间的差;
- value_type 元素类型;
- reference/const_reference 元素的左值类型;
提到这些类型,是希望提醒自己要深入了解内置的类型,在定义与容器有关的定义的时候,尽量声明成以上的几种类型,如string的下脚标最好声明成size_type类型,这样在和s.size()进行大小判断时不会出现比较奇怪的结果(如果声明成int类型,脚标进行变化之后,偶尔会出现比较奇怪的现象)。
容器之间的操作主要有以下几种:
- 容器的初始化;
- 向容器添加元素;
- 向容器删除元素;
1. 容器初始化
- 默认初始化;
- 利用另一个容器的拷贝;
- 利用指向同一个序列的迭代器;
- 列表初始化
vector<int> vec = {1,2,3,4,5,6,7,8,9,0};//列表初始化;
list<int> lst;//默认构造函数;
string s;//默认构造函数
vec<int> vec_copy(vec);//另一个容器的拷贝
vec<int> vec2(vec.begin(),vec.end());//指向一个序列的迭代器;
以上四种初始化方式中,默认初始化并不需要注意什么;在使用列表初始化的时候,列表中的元素个数意味着容器初始化之后的大小,这一点和内置的数组列表初始化有些不一样,值得注意一下;利用拷贝构造函数进行初始化的时候,注意两个容器的类型以及容器所包含的元素类型都应该一致;使用迭代器进行初始化的时候,应该注意迭代器指向同一个序列;
2. 容器添加删除元素
容器添加元素主要有以下几种操作:
- push_front/push_back;
- insert/emplace
- pop_front/pop_back;
- erase/clear;
在这些添加删除操作中,有些容器支持,有些容器不支持,我们应当予以区分;这些函数完成的操作,我们很容易从函数字面上加以理解,需要注意的事这些函数的参数以及返回值,以及当容器的大小发生改变时,迭代器可能会失效的情况;以后会以vector和string为例,重点整理一下这些成员函数,在这里就不再就只提提我们需要注意的地方;
另外forward_list是个比较特殊的容器,它的操作函数如下所示:
- before_begin()/before_cbegin()
- insert_after()/emplace_after()
- erase_after()
因为forward_list是单向链表,再删除元素时无法访问前驱,这就导致了这个容器的特异性;删除和添加元素传递的迭代器都是指向操作元素(添加或删除)之前的那个元素,注意到这一点,就容易理解forward_list和其他容器的不同乐;
=============================
个人总结:这一章内容的知识虽然并不难,但涉及到的细节有点多,全部记下来有点困难;这对我使用标准库容器编程章造成了一定的障碍;在实际编程中,知道用哪种容器,知道用哪种函数,但因为不太清楚函数模板之间的差别(参数和返回值的差别),有些时候甚至会和标准库算法里面的某些函数产生混乱,因此觉得需要梳理;在编程练习过程当中,vector和string使用频率最高,故决定在接下来的时间,会重点以vector和string为例梳理一下容器的成员函数,以加深的理解;
==============================
感觉书看了不少,却还一直在基础知识徘徊,可能最大的原因就是代码量不够。-> 代码量成了阻碍我深入学习C++的瓶颈;