一、容器库概述
1.1 迭代器
所有标准库容器都可以使用迭代器,但是只有少数几种支持下标运算符(vector 、deque 、map )。有效迭代器指向容器中的某个元素,或者指向容器中尾元素的下一个位置,后者成为尾后迭代器,其余都是无效的。
迭代器运算符 使用== 和!= 可以比较两个有效迭代器是否相等;和指针类似,也能通过解引用有效迭代器获取它所指的元素(不包括尾后迭代器)。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/3ff96227615d43a990dbc5e78adf3f23.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQyNTcwNjAx,size_16,color_FFFFFF,t_70) 一个迭代器范围由一对迭代器表示,一个指向容器C中的元素,一个是容器C的尾后迭代器,如左闭合区间[begin, end) 。
1.2 容器类型别名
通过类型别名,可以在不了解容器中元素类型的情况下使用它。如果需要元素类型,可以使用value_type ,如果需要一个元素的引用可以使用reference 或const_reference 。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/e26a139685a84e78b19fb9f0a86bdbf4.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQyNTcwNjAx,size_16,color_FFFFFF,t_70)
1.3 容器的定义与初始化
array 与其他容器不同,大小也是其类型的一部分,定义时除了指定元素类型,还要指定容器大小,如:array<int, const_n> a1; 。
C c1;
array<int, const_n> a1;
C c2(c1);
C c3 = c1;
C c4 { a, b, c... };
C c5 = { a, b, c... };
C c6(begin, end);
C c7(n);
C c8(n, t);
1.4 赋值和swap
容器赋值运算:assign 只适用于顺序容器;array 的类型包括元素数目,所以可能改变大小的赋值都不支持。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/284535c7f31749acb6aae1b48418c26a.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQyNTcwNjAx,size_16,color_FFFFFF,t_70) 赋值运算符要求左右两边的运算对象具有相同的类型,它将左边容器中的全部元素,替换为右边容器中元素的拷贝。
- 对于非
array 类型,赋值运算与左右两边容器的大小没有关系,如c1.size() == 1 ,c2.size() == 3 ,赋值完后两个size 都为3 。 - 而
array 类型与内置数组不同,它允许赋值,赋值号左右两边的类型必须相同(array 的大小也属于类型)。由于右边运算对象的大小可能与左边运算对象的大小不同,因此array 类型不支持assign ,也不允许用值列表赋值,但是可以列表初始化。 array<int, 3> a1 = { 1, 2, 3 }
array<int, 3> a2 = { 0 };
a1 = a2;
a2 = { 0 };
1)assign(仅顺序容器)
顺序容器定义了一个名为assign 的成员,允许我们从一个不同但相容的类型赋值,或者从容器的一个子序列赋值。由于被旧元素替换,因此传递给assign 的新迭代器不能指向调用assign 的容器。
list<string> names;
names.push_back("123");
vector<const char*> old_style;
old_style.push_back("abc");
list<string>::iterator names_it_begin = names.begin();
list<string>::iterator names_it_end = names.end();
for (list<string>::iterator it = names_it_begin; it != names_it_end; it++)
cout << *it << endl;
names.assign(old_style.begin(), old_style.end());
for (list<string>::iterator it = names_it_begin; it != names_it_end; it++)
cout << *it << endl;
2)swap
二、顺序容器
1.1 顺序容器的类型
除了array 外,其他容器都有高效的内存管理;array 大小固定,不支持添加删除等改变数组大小的操作,现代C++更应该使用array 而不是内置数组;forward_list 设计目标是与最好的手写单链表性能相当,因此没有size 操作,因为size 的保存和计算都会产生额外的开销。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/9db52353a4b4415fad52e94163a10998.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQyNTcwNjAx,size_16,color_FFFFFF,t_70)
1.2 确定使用哪种容器
选择容器遵从以下基本原则:
- 通常使用
vector 是最好的选择,如果有足够的理由可以选择其他容器。 - 需要随机访问,或在头部尾部插入删除,
vector 、deque 。 - 需要在容器中间插入删除,
list 、forward_list 。 - 如果程序只需在读取输入时才需要在中间位置插入元素,随后需要随机访问。
a)先将插入元素放在vector 的尾部,再调用sort 函数重排容器。 b)考虑插入阶段使用list ,输入完成后将list 中的内容拷贝到vector 中。 - 如果不确定使用哪种容器,可以在程序中只是用
vector 和list 的公共操作:使用迭代器,不使用下标,这样在必要时可以切换。
1.3 容器的定义与初始化
vector<int> vec1;
vector<int> vec2(vec1);
vector<int> vec3(vec1.begin(), vec1.end());
vector<int> vec4(10);
vector<int> vec5(10, 4);
vector<string> vec6(10, "hello");
vector<int> vec7 { 10 };
vector<string> vec8 { "qwe", "asd", "zxc" };
vector<string> vec9 = { "qwe", "asd", "zxc" };
1.4 容器基本操作
在这里插入代码片
二、关联容器
三、容器适配器
四、容器总结
|