《C++ Primer》读书笔记第九章-1- 顺序容器概述 And 容器库概览
2017-09-18 23:59
477 查看
笔记会持续更新,有错误的地方欢迎指正,谢谢!
不同容器在两个方面的性能不同:
向容器中添加或删除元素;
访问容器中的元素。
详情如下:
标准库容器性能通常优于同类数据结构。
可以看到每个容器都对性能有所侧重,都有不同的灵活度。
那我们在选择容器的时候应该怎么选呢?
除非你有很好的理由选择其他容器,否则一律用vector;
程序要求随机访问,就用vector或deque;
程序有很多小的元素,需要很大的额外开销,不要用list或forward_list,因为它们再去连其他内存开销更大;
如果程序要在容器中间插入或删除元素,应使用list或forward_list;
程序只在头尾插入删除元素,用deque。
总结:在实际应用的时候,你一定要自己衡量好性能,只要你掌握了表格中各个容器的特点,相信你能做出最合适的选择!
对容器可以保存的元素类型的限制:
顺序容器几乎可以保存任意类型的元素,包括它自己。也有一些例外,比如类类型。
例子:我要保存一个类类型的对象,而这个类没有默认构造函数,于是,我得自己给它提供一个元素初始化器:
迭代器可加可减,但forward_list不支持减,理由不用解释。
reverse_iterator按逆序寻址的迭代器,rbegin()是尾迭代器,crend()表示前迭代器。
要遍历的话,就从crend()递减到rbegin()。
当不需要修改时,最好用cbegin。
补充:
explicit构造函数是用来防止隐式转换的。请看下面的代码:
与顺序容器大小相关的构造函数:
总结:如果元素类型是内置类型或有默认构造函数的类类型,可以在初始化的时候只为构造函数提供一个容器大小参数;如果没有默认构造函数,必须要显式地提供初值(具体例子可见本文“容器库概览”)。
标准库array具有固定大小:
列表初始化的数目必须等于或小于array的大小;花括号列表只能初始化不能赋值。
array的大小也是类型的一部分:
我们不能对内置数组进行拷贝,但array可以(可能这也是为什么搞出array的原因):
使用swap:
顺序容器概述
前言:这部分的内容在写程序的时候肯定是处处都能用到的,而且会让你的程序很简洁。本章是第三章的拓展,详细地介绍了标准库顺序容器的知识。一个容器就是一些特定类型对象的集合。不同容器在两个方面的性能不同:
向容器中添加或删除元素;
访问容器中的元素。
详情如下:
容器 | 特征 |
---|---|
vector | 可变大小数组,支持快速随机访问,在尾部之外的位置插入或删除元素较慢。(因为在内存中元素是连续存储的,所以快速随机访问(想访问谁就访问谁)很容易,头的位置再加上你要访问的顺序就好,添加删除元素就需要移动它之后的所有元素,所以慢) |
list | 双向链表,只支持双向顺序访问,不支持随机访问,在任意位置插入删除都快,内存中不连续,通过指针指向前后元素 |
deque | 双端队列。支持快速随机访问,在头尾位置插入或删除元素很快。 |
forward_list | 单向链表,只支持单向顺序访问,在链表任意位置插入删除都快。也就是:不支持反向容器迭代器,且其迭代器不支持递减运算。 |
array | 固定大小数组,支持快速随机访问,不能添加或删除 |
string | 与vector类似,专门用于保存字符,随机访问快,在尾部插入删除快 |
可以看到每个容器都对性能有所侧重,都有不同的灵活度。
那我们在选择容器的时候应该怎么选呢?
除非你有很好的理由选择其他容器,否则一律用vector;
程序要求随机访问,就用vector或deque;
程序有很多小的元素,需要很大的额外开销,不要用list或forward_list,因为它们再去连其他内存开销更大;
如果程序要在容器中间插入或删除元素,应使用list或forward_list;
程序只在头尾插入删除元素,用deque。
总结:在实际应用的时候,你一定要自己衡量好性能,只要你掌握了表格中各个容器的特点,相信你能做出最合适的选择!
容器库概览
这部分讲述所有容器的共性,每个容器都定义在一个头文件中,文件名和类型名相同,例如,deque定义在头文件deque中。容器均定义为模板类,我们必须提供额外信息来生成特定的容器类型。对容器可以保存的元素类型的限制:
顺序容器几乎可以保存任意类型的元素,包括它自己。也有一些例外,比如类类型。
例子:我要保存一个类类型的对象,而这个类没有默认构造函数,于是,我得自己给它提供一个元素初始化器:
//假定a是一个没有默认构造函数的类型 vector<a> v1(10, init); //正确:10个a类型的元素init(也就是10个a的对象) vector<a> v2(10); //错误:没有默认构造函数,无法初始化。
迭代器
之前介绍过,这里就不介绍了。迭代器可加可减,但forward_list不支持减,理由不用解释。
反向迭代器
大多数容器还提供反向迭代器,反向迭代器++就是上一个元素。reverse_iterator按逆序寻址的迭代器,rbegin()是尾迭代器,crend()表示前迭代器。
要遍历的话,就从crend()递减到rbegin()。
begin和end成员
list<string> a = {"1", "2", "3"}; auto it1 = a.begin(); //此auto为list<string>::iterator auto it2 = a.rbegin(); //list<string>::reverse_iterator auto it3 = a.cbegin(); //list<string>::const_iterator auto it4 = a.crbegin(); //list<string>::const_reverse_iterator
当不需要修改时,最好用cbegin。
容器定义和初始化
每个容器类型都定义了一个默认构造函数。除了array之外,其他容器的默认构造函数都会创建一个指定类型的空容器。下图已经说得很清楚了:补充:
explicit构造函数是用来防止隐式转换的。请看下面的代码:
class Test1 { public: Test1(int n)//普通构造函数 { num=n; } private: int num; }; class Test2 { public: explicit Test2(int n)//explicit(显式)构造函数 { num=n; } private: int num; }; int main() { Test1 t1=12;//隐式调用其构造函数,成功。 Test2 t2=12;//不能隐式调用其构造函数,编译错误。 Test2 t2(12);//显式调用其构造函数,成功。这种就叫显示构造函数!!! return 0; }
与顺序容器大小相关的构造函数:
vector<int> a1(10, -1);//10个-1 vector<int> a2(10);//10个0 vector<string> a3(10);//10个空string
总结:如果元素类型是内置类型或有默认构造函数的类类型,可以在初始化的时候只为构造函数提供一个容器大小参数;如果没有默认构造函数,必须要显式地提供初值(具体例子可见本文“容器库概览”)。
标准库array具有固定大小:
列表初始化的数目必须等于或小于array的大小;花括号列表只能初始化不能赋值。
array的大小也是类型的一部分:
array<int, 3>; //类型是3个int的数组 array<int, 10> a1; //10个0 array<int, 3> a2 = {1, 2, 3}; //列表初始化 array<int, 3> a3 = {5}; //正确的。a3为5, 0, 0
我们不能对内置数组进行拷贝,但array可以(可能这也是为什么搞出array的原因):
array<int, 3> a = {1, 2, 3};//列表初始化 array<int, 3> copy = a;//拷贝
赋值和swap
vector<int> a1 = {1, 2, 3, 4, 5}; a1 = {1, 2}; //这样正确,a1变为1,2。 array<int, 5> b1 = {1, 2, 3, 4, 5}; b1 = {1}; //这样错误。只有array,花括号列表只能初始化不能赋值。
使用swap:
vector<string> s1(10); vector<string> s2(20); swap(s1, s2); //交换后,s1有20个元素,s2有10个元素。
容器大小操作
名称 | 含义 |
---|---|
size | 返回容器中元素个数 |
empty | 只在size为0时返回true |
max_size | 返回一个大于或等于该容器所能容纳的最大元素个数 |
关系运算符
容器装的元素类型支持关系运算,我们才能来用它。比如:内置类型vector<int> v1 = {1, 3, 5, 7, 9, 12}; vector<int> v2 = {1, 3, 9}; vector<int> v3 = {1, 3, 5, 7}; v1 < v2; v1 > v3;
相关文章推荐
- 《C++ Primer》读书笔记第九章-2-顺序容器操作 And vector增长问题
- 读书笔记《C++ Primer》第五版——第九章 顺序容器
- 《C++ Primer》读书笔记——第九章_顺序容器
- C++ primer 读书笔记 第九章 顺序容器
- 《C++ Primer》读书笔记-第九章 01 顺序容器
- 《C++ Primer》读书笔记-第九章 03 顺序容器操作
- c++ primer 读书笔记 第九章 顺序容器有那些 vector list deque stack queue priority-queue
- 《C++ Primer》读书笔记第九章-3-额外的string操作 And 容器适配器
- c++ primer (5th) 第九章,顺序容器
- C++ Primer 读书笔记: 第9章 顺序容器
- C++ primer 读书笔记系列——(6)顺序容器(三)之再谈string类型和容器适配器
- C++ Primer : 第九章 : 顺序容器的定义、迭代器以及赋值与swap
- C++ Primer 读书笔记 Chapter 9 顺序容器
- C++ Primer 【第四版】第九章 顺序容器
- 【C++ Primer】【学习笔记】【第九章】顺序容器之:vector容器的自增长
- 【c++ primer 笔记】第九章 顺序容器
- 《C++ primer(第四版)》读书笔记8-第9章 顺序容器
- C++ Primer 第九章 顺序容器
- C++ Primer 第九章 顺序容器
- C++ Primer 第四版读书笔记(八)之顺序容器