C++STL学习记录
C++ STL容器有哪些常用成员函数和成员变量? - Dotcpp编程
一、容器
1.访问方式
迭代器、下标[]和at()、指针。
2.常用成员函数和变量
C++ STL容器有哪些常用成员函数和成员变量? - Dotcpp编程
3.向量数组vector
3.1元素的增删查改
增:尾插法push_back()和emplace_back(),在指定位置前插入元素insert()和emplace()。
删:
| 函数 | 参数及介绍 |
|---|---|
pop_back() | 参数: 无 介绍: 删除向量的最后一个元素,大小减1,容量不变 |
erase(position) | 参数: const_iterator position介绍: 删除指定位置的单个元素,返回指向被删除元素之后元素的迭代器 |
erase(first, last) | 参数: const_iterator first, const_iterator last介绍: 删除 [first, last)范围内的元素,返回指向最后一个被删除元素之后元素的迭代器 |
clear() | 参数: 无 介绍: 删除所有元素,大小变为0,容量保持不变 |
resize(new_size) | 参数: size_type new_size介绍: 如果 new_size小于当前大小,则删除末尾的多余元素 |
查、改:通过访问方式访问向量中的元素+front()、back()。
3.2向量大小相关成员函数
size()、capacity()、reserve(n)、resize()、swap()和shrink_to_fit()、empty()。
4.deque双端队列
4.1增删查改
增:push_front()、push_back()、emplace_front()、emplace_back()、insert()、emplace()。
删:pop_front()、pop_back()、erase()、clear()、指定元素全清remove()(标准库中的)+erase()。
查、改:通过访问方式访问向量中的元素+front()、back()。
4.2向量大小相关成员函数
size()、max_size()、capacity()、resize()、swap()和shrink_to_fit()、empty(),没有预存函数。
5.list双向列表
5.1访问方式
仅支持迭代器。
5.2增删查改
增:push_front()、push_back()、emplace_front()、emplace_back()、insert()、emplace()、splice()。
删:pop_front()、pop_back()、erase()、clear()、unique()、remove()和remove_if()(这两个remove函数是list容器类中定义的,不是标准库中的)。
查、改:通过访问方式访问向量中的元素+front()、back()。
5.3向量大小相关成员函数
size()、max_size()、capacity()、resize()、swap()和shrink_to_fit()、empty(),没有预存函数。
5.4list迭代器
支持++、--但不支持+n、-n随机访问操作。
5.5forward_list单列表
类比list,但是迭代器仅支持从前往后,仅支持头增头删,没有back()、size()函数等等。
6.关联容器map(自动排序、有序、键值唯一性)
6.1迭代器(相对于序列式特有)(所有map迭代器只能进行++或--操作,不能+5或-8随机访问)
find()、lower_bound()、upper_bound()、equal_range()(equal_range()主要在multimap中用的多,map没啥用)(参数均为Key值,有则返回迭代器,无则返回end())。
6.2访问方式
迭代器(注意获取迭代器的几种方式)、at()、[]、指针,注意迭代器返回的是整个键值对的指针,还需要->second获取value;在知道key值的情况下,我们最好使用at(),其次是find(),最后是'[]',原因在于如果没有存在key="输入参数"的元素,at()会报错而find()会返回容器尾后迭代器end(),而'[]'直接给你创建一个“[输入的key]=默认值的元素(不同数据类型有不同的默认值),虽然不存在报错问题,但是却失去了对数据的绝对控制,破坏数据的完整性。
6.3增删查改
增:[](这里如果已存在key,则进行覆盖)、insert()(可一次插入多个)、emplace()(单个效率高)、emplace_hint()(有返回值,批量插入时效率最高)。
删:erase()、clear()。
查、改:通过访问方式。
7.multimap(自动排序、有序、键值可重复)
类似map,区别在于访问方式只能通过迭代器和指针。
8.set容器(自动排序去重、有序、键值唯一且键值相等且不能直接修改键对应的值)
8.1迭代器(相对于序列式特有)(所有set迭代器只能进行++或--操作,不能+5或-8随机访问)
find()、lower_bound()、upper_bound()、equal_range()、count()。
8.2访问方式
迭代器、指针。
8.3增删查改
增:insert()(可一次插入多个)、emplace()(单个效率高)、emplace_hint()(插入时注意set会自动排序和去重)。
删:erase()、clear()。
查、改:通过访问方式,修改只能先删除原有键值对,在增加修改的键值对。
9.multiset(自动排序、有序、键值可重复且键值相等)
可通过仿函数修改排序顺序,标准库<functional>。
10.无序关联容器底层逻辑
哈希表:
- 核心思想是键值对;
- 创建过程:通过哈希算法将任意输入转为统一形式输出(如数组下标),并在对应数组下标(该存放数组称为桶数组)位置存放该输入值;
- 使用方式:类似创建过程,通过哈希表能实现高效查询,而避免遍历查询。
无序关联容器可视为基于哈希表的数组+链表:
创建过程:向堆区开辟了一段连续空间(可理解为数组),空间大小为n,每个单位空间被称为“桶”且能够存储一个头指针,头指针“牵引"着一个单向链表(双向链表太费内存了)。当我们输入一个键值对时,键会被哈希函数转变成哈希值hash,随后由hash&(n-1)找到在桶数组中对应的下标以及数组中存放的头指针,将键值对作为一个整体被封装在该头指针指向的链表的节点中。

无序关联式容器内都维护着一个重要的成员变量——load_factor(),它叫做负载因子,数据类型为float,其值=插入键值对总量/桶数量,功能是分析键值对的分布情况,当负载因子<0.5时,说明不管是空间利用率还是访问效率都比较高,反之。下面我们通过代码来分析插入键值对对负载因子的影响。
在存储基本数据类型时,键(key)能够通过哈希函数转为哈希值(数据类型为size_t),当我们的键为自定义数据类型时,就需要我们重新定义哈希函数和重载operator'=='运算符。
11.unordered_map(无序,键值对唯一)
11.1迭代器
由于哈希表的特性,使得unordered_map容器变得“无序”,所以它不在乎“顺序”没有“反向”这个概念,属于前向迭代器,只能进行++操作。
unordered_map容器有正向迭代器begin()、end(),常量迭代器cbegin()、cend()。
11.2访问方式
迭代器(获取迭代器的方式如find())、at()、[]。
11.3增删查改
增:[]、insert()、emplace()、emplace_hint()。
删:erase()、clear()。
查改:访问方式。
12.unordered_multimap(无序,键值可重复)
类似unordered_map(),区别在于访问方式只能通过迭代器和指针,且重点使用equal_range()。
13.unordered_set(去重,无序,键值一体且唯一因此不能直接修改键值对)
类似set()。
14.unordered_multiset(无序,键值一体可重复且因此不能直接修改键值对)
类似multiset()。
15.容器的选择
通常情况下,我们一般会面对以下四种需求:
1. 随机访问。
2. 频繁增删。
3. 查找且有序。
4. 快速查找。
面对第一种需求,我们尽量选择vector容器,因为它既拥有数组的连续访问性又能够“动态扩展”,其次再选择array容器或是deque容器。面对第二种需求,我们不用多想,肯定选择list容器,因为我们需要频繁对元素进行增删,如果你选vector这种容器,又要扩容又要复制,得多费时间啊。面对第三种需求,用map容器就最为合适了,就像我们查字典一样,根据拼音或部首进行字的查询,直接跳到对应的地方查字,就不用一页一页地找。最后一种数据库里最常见,比如银行系统就需要根据用户账户快速定位用户全部信息,及时更新数据。
二、迭代器
注意迭代器是由容器类型定义的,不是由容器对象定义,begin()、end()、rbegin()、rend()、cbegin()、cend()、crbegin()、crend()。
迭代器的类型由功能决定而不是函数决定,即map容器的begin()返回的是双向迭代器,而unordered_multimap的begin()返回的是前向迭代器。
反向迭代器的移动,从rbegin到rend也是++操作(前向++)。
vector是动态数组,增减元素都会导致位置变化,所以在使用迭代器时要及时更新迭代器,否则导致迭代器失效,造成程序崩溃等未定义行为,vector和deque均需要及时更新迭代器。但list通过指针连接上下节点,即使增减元素也不会改变原来元素的位置,因此不用更新迭代器。
更多推荐


所有评论(0)