1. STL基础
1.4 熟练使用STL标准库是每个C++程序员的必备技能!
- 写多个函数 -> 类封装+重载 -> 模板、泛型
- 使用了泛型的代码:模板
- 泛型也是一种数据类型
1.6 C++ STL要学习哪些知识?
- 容器、算法、迭代器
- 适配器、配接器
- 空间配置器、内存分配器
- 仿函数、函数对象:如果一个类将 () 运算符重载为成员函数,这个类就称为函数对象类,这个类的对象就是函数对象(又称仿函数)
1.8 什么是GNU开源精神,它经历了怎样的发展历程?
- 开放源代码的观念源自美国人 Richard Stallman(理察·史托曼,如图 1 所示),他认为私藏源代码是一种违反人性的罪恶行为,而如果能与他人分享源代码,便可以让其他人从中学习,并回馈给原始创作者。封锁源代码虽然可以程度不一地保障“智慧可能衍生的财富”,却阻碍了使用者从中学习和修正错误的机会。
2. STL序列式容器
2.1 C++ STL容器是什么?
- 三种容器
- 序列容器:array、vector、list、deque
- 排序容器:map、set、multimap、multiset
- 哈希容器:unordered_map、unordered_set、unordered_multimap、unordered_multimap
- 排序容器 + 哈希容器 = 关联容器
2.2 C++ STL迭代器是什么?
-
五种迭代器:输入、输出、前向、双向、随机访问 -
前向/双向只能!=判断、随机可以<、> != v.end() 和 < v.end() 的区别
-
容器 | 对应的迭代器类型 |
---|
array | 随机访问迭代器 | vector | 随机访问迭代器 | deque | 随机访问迭代器 | list | 双向迭代器 | set / multiset | 双向迭代器 | map / multimap | 双向迭代器 | forward_list | 前向迭代器 | unordered_map / unordered_multimap | 前向迭代器 | unordered_set / unordered_multiset | 前向迭代器 | stack | 不支持迭代器 | queue | 不支持迭代器 |
-
尽管不同容器对应着不同类别的迭代器,但这些迭代器有着较为统一的定义方式: -
迭代器定义方式 | 具体格式 |
---|
正向迭代器 | 容器类名::iterator 迭代器名; | 常量正向迭代器 | 容器类名::const_iterator 迭代器名; | 反向迭代器 | 容器类名::reverse_iterator 迭代器名; | 常量反向迭代器 | 容器类名::const_reverse_iterator 迭代器名; |
-
注意,以上 4 种定义迭代器的方式,并不是每个容器都适用
2.3 序列式容器
- array、vector、deque、list、forward_list
- stack、queue
2.4 C++ array(STL array)序列容器用法详解
2.6 C++ STL array容器访问元素的几种方式
- []没有实现边界检查的功能
- at()越界抛出异常
- get<n>() 参数的实参必须是一个在编译时可以确定的常量表达式
- data()返回指针
2.8 C++ STL vector容器用法详解
2.9 C++ STL vector容器迭代器的用法
- vector 容器在申请更多内存的同时,容器中的所有元素可能会被复制或移动到新的内存地址,这会导致之前创建的迭代器失效
- 每当vector容量发生变化时,都要对之前创建的迭代器重新初始化一遍
2.11 C++ vector容量(capacity)和大小(size)的区别
- resize()改变元素个数
- reserve()改变容量
- 容量和大小类型都是 vector::size_type 类型
2.13 C++ STL vector添加元素(push_back()和emplace_back())
- push_back() 向容器尾部添加元素时,首先会创建这个元素,然后再将这个元素拷贝或者移动到容器中(如果是拷贝的话,事后会自行销毁先前创建的这个元素);而 emplace_back() 在实现时,则是直接在容器尾部创建这个元素,省去了拷贝或移动元素的过程。
- emplace == insert
- emplace_back == push_back
- C++11
2.14 C++ STL vector插入元素(insert()和emplace())
2.16 如何避免vector容器进行不必要的扩容?
- 当容器进行扩容后,之前和该容器相关的所有指针、迭代器以及引用都会失效
- 使用reserve()预留
2.17 vector swap()成员方法还可以这样用!
2.18 切忌,vector不是存储bool类型元素的vector容器!
- 避免使用 vector<bool>:vector<bool> 并不是一个 STL 容器、vector<bool> 底层存储的并不是 bool 类型值
- vector不能返回一个指向单个比特位的引用(为了节省空间,vector<bool> 底层在存储各个 bool 类型值时,每个 bool 值都只使用一个比特位(二进制位)来存储。也就是说在 vector<bool> 底层,一个字节可以存储 8 个 bool 类型值。在这种存储机制的影响下,operator[ ] 势必就需要返回一个指向单个比特位的引用,但显然这样的引用是不存在的。)
- 用 deque<bool> 或者 bitset 来替代 vector<bool>
2.21 深度剖析deque容器底层实现原理*
- 一个deque是由map数组组成的
- 一个map对应一个迭代器
- 每个迭代器有四个元素
- splice()操作
2.22 怎样访问deque容器中存储的元素?
- at() 会抛出越界异常
- 可以通过[]访问
- 无data()方法
2.25 C++ STL list迭代器及用法(详解版)
- 值得一提的是,list 容器在进行插入(insert())、接合(splice())等操作时,都不会造成原有的 list 迭代器失效,甚至进行删除操作,而只有指向被删除元素的迭代器失效,其他迭代器不受任何影响。
2.26 一文彻底搞懂list容器的底层实现机制!
- list_node
- list
- list_iterator
2.31 forward_list容器:高效率的list容器!
- forward_list是C++11新增的
- 无size(),可以用distance()
3. STL关联式容器
3.1 C++ STL关联式容器是什么?
- 红黑树:map、multimap、set、multiset
- 哈希表:unordered_
3.2 C++ STL pair类模板,快速生成键值对元素!
- pair在<utiltiy>中
- 将 make_pair() 函数的返回值(是一个临时对象)作为参数传递给 pair() 构造函数时,其调用的是移动构造函数,而不是拷贝构造函数
3.3 C++ STL map容器详解
- map容器都是pair对象
- 默认升序
- lower_bound():第一个大于等于
- upper_bound():第一个大于
3.4 C++ STL map容器迭代器(精讲版)
3.5 C++ STL map获取键对应值的几种方法
- 只有当 map 容器中确实存有包含该指定键的键值对,借助重载的 [ ] 运算符才能成功获取该键对应的值;反之,若当前 map 容器中没有包含该指定键的键值对,则此时使用 [ ] 运算符将不再是访问容器中的元素,而变成了向该 map 容器中增添一个键值对
- at()
3.7 C++ map容器operator[]和insert()效率对比(深度剖析)
- 总的来说,读者可记住这样一条结论:当实现“向 map 容器中添加新键值对元素”的操作时,insert() 成员方法的执行效率更高;而在实现“更新 map 容器指定键值对的值”的操作时,operator[ ] 的效率更高。
3.8 C++ STL map emplace()和emplace_hint()
- emplace()
- emplace_hint():多了个插入位置,但最后的位置还是排序的位置
3.9 C++ map容器3种插入键值对的方法,谁的效率更高?
- 插入键值对的时候,优先考虑emplace()和emplace_hint()
3.10 C++ STL multimap容器
- multimap和map都在<map>
- multimap没有at(),[](相比map)
3.11 C++ STL set容器
- set要求键和值必须相同
- 最正确修改set中元素的方法是:先删除该元素再添加
3.12 C++ STL set容器迭代器
3.15 C++ STL set删除数据
3.17 如何自定义C++ STL关联式容器的排序规则?
排序规则 | 功能 |
---|
std::less<T> | 底层采用 < 运算符实现升序排序,各关联式容器默认采用的排序规则。 | std::greater<T> | 底层采用 > 运算符实现降序排序,同样适用于各个关联式容器。 | std::less_equal<T> | 底层采用 <= 运算符实现升序排序,多用于 multimap 和 multiset 容器。 | std::greater_equal<T> | 底层采用 >= 运算符实现降序排序,多用于 multimap 和 multiset 容器。 | | |
- 注意,当关联式容器中存储的元素类型为结构体指针变量或者类的指针对象时,只能使用函数对象的方式自定义排序规则,此方法不再适用。
- 可以使用成员函数或者友元函数的形式实现。其中,当以成员函数的方式重载 < 运算符时,该成员函数必须声明为 const 类型,且参数也必须为 const 类型:同样,如果以友元函数的方式重载 < 运算符时,要求参数必须使用 const 修饰:
3.18 如何修改关联式容器中键值对的键?
- map 和 multimap 容器只能采用“先删除,再添加”的方式修改某个键值对的键。原因很简单,C++ STL 标准中明确规定,map和 multimap 容器用于存储类型为 pair<const K, V> 的键值对。
- 和 map、multimap 不同,C++ STL 标准中并没有用 const 限定 set 和 multiset 容器中存储元素的类型。换句话说,对于 set<T> 或者 multiset<T> 类型的容器,其存储元素的类型是 T 而不是 const T。
- C++ STL 标准不允许用户借助迭代器来直接修改 set 或者 multiset 容器中的元素
- 那么,如何才能正确修改 set 或 multiset 容器中的元素呢?最直接的方式就是借助 const_cast 运算符,该运算符可以去掉指针或者引用的 const 限定符。
4. STL无序关联式容器
4.1 C++ STL无序容器(哈希容器)是什么?
- 底层用的是哈希表(开链法)
- 涉及大量遍历操作,首选关联式容器;反之更多的是通关键获取值,首选无序
4.3 深度剖析C++无序容器的底层实现机制
4.4 C++ unordered_map迭代器的用法
- 在操作 unordered_map 容器过程(尤其是向容器中添加新键值对)中,一旦当前容器的负载因子超过最大负载因子(默认值为 1.0),该容器就会适当增加桶的数量(通常是翻一倍),并自动执行 rehash() 成员方法,重新调整各个键值对的存储位置(此过程又称“重哈希”),此过程很可能导致之前创建的迭代器失效。
4.9 C++ STL unordered_multimap容器
- 无序容器中存储的各个键值对,都会哈希存到各个桶(本质为链表)中。而对于 unordered_multimap 容器来说,其存储的所有键值对中,键相等的键值对会被哈希到同一个桶中存储。
4.12 如何自定义C++ STL无序容器的哈希函数和比较规则?(超级详细)
4.13 C++ STL容器这么多,怎样选出最适合的?
- 四类:
- 序列式容器:array、vector、deque、list 和 forward_list;
- 关联式容器:map、multimap、set 和 multiset;
- 无序关联式容器:unordered_map、unordered_multimap、unordered_set 和 unordered_multiset;
- 容器适配器:stack、queue 和 priority_queue。
- 根据连续还是分散的存储空间:
- 采用连续的存储空间:array、vector、deque;
- 采用分散的存储空间:list、forward_list 以及所有的关联式容器和哈希容器。
5. STL容器适配器
- stack、queue、priority_queue
- deque、deque、vector(底层使用的容器)
- vector、deque、list(stack用的)
- deque、list(queue用的)
- vector、deque(priority_queue用的)
- 简单的理解容器适配器,其就是将不适用的序列式容器(包括 vector、deque 和 list)变得适用
- 第二个参数可以选择底层使用的容器:
6. STL迭代器适配器
- 五种迭代器:输入、输出、前向、双向、随机访问
- 四种迭代器适配器:反向、安插型、流、移动
- 四种定义方式:正向、常量正向、反向、常量反向
- C++ 编译器的隐式转换仅支持以下 2 种情况:
- 将 iterator 类型的迭代器隐式转换为 const_iterator 类型的迭代器;
- 将 reverse_iterator 类型的迭代器隐式转换为 const_reverse_iterator 类型的迭代器。
- const_cast 的功能仅是去掉某个类型的 const 修饰符,但 const_iterator 和iterator 是完全不同的 2 个类,所以不能用const_cast将const迭代器转换为非const
- 可以用advance和distance
- advance()、distance()
- prev()、next()
7. C++常用算法
|