一、迭代器
- 迭代器:指针的抽象,也叫泛型指针。
- 迭代器是容器和算法之间的接口。
- 通过迭代器可以遍历容器中的序列,也可以遍历输入/输出流中的输入序列/输出序列。
- 当两个迭代器对象指向同一容器中的同一元素 ,或当二者指向同一容器中最后一个元素的下一个位置时,两个迭代器相等。
迭代器的类别 | 功能 | 支持的操作 | 备注 |
输入迭代器 | 读 | * -> = ++ == != | 输入迭代器的解引用操作的结果只能作为右值使用 |
输出迭代器 | 写 | * ++ = | 输出迭代器的解引用操作的结果只能作为左值使用 |
正向迭代器 | 读/写 | 输入/输出迭代器支持的所有操作 | 正向迭代器的解引用操作的结果即可作为左值又可作为右值使用。forward_list容器中的迭代器。 |
双向迭代器 | 读/写 | 正向迭代器支持的所有操作以及-- | STL容器提供的迭代器都至少达到双向迭代器的要求。 |
随机访问迭代器 | 读/写 | 双向迭代器支持的所有操作以及:两个迭代器之间的比较< <= > >=,迭代器对象与整数n之间的+ += - -=,两个迭代器相减-,下标操作[] | 当两个迭代器是同一容器中的迭代器时,比较操作才有意义;下标操作iter[n]==*(iter+n)。 |
//distance();
template<typename InputIterator>
typename iterator_traits<InputIterator>::difference_type distance (InputIterator first, InputIterator last);
//Return distance between iterators
//Calculates the number of elements between first and last
//advance()
template <typename InputIterator, typename Distance>
void advance (InputIterator& i, Distance n);
//Advances the iterator i by n elements.
二、容器
- 容器:包含元素对象的对象。
2.1顺序容器
- array
- vector
- deque(双端队列)
- list(双链表)
- forward_list(单链表)
2.1.1容器对象的定义及初始化
函数使用形式 | 说明 |
C<T>c; | 创建空容器c |
C<T>c(cx); | 创建容器c作为cx的副本,c和cx必须是同类型且元素类型也相同的容器 |
C<T>c(b,e); | 创建容器c,并用迭代器[b,e)之内的元素的副本对c进行初始化 |
C<T>c(n,t); | 创建容器c,并在其中存放n个值为t的元素,t必须是T类型的值,或者可以转换为T类型的值 |
C<T>c(n); | 创建容器c,并在其中存放n个元素,每个元素都是T类型的值初始化元素 |
2.1.2容器中定义的类型别名
类型别名 | 说明 |
iterator | 指向元素的迭代器的类型 |
const_iterator | 指向元素的常量迭代器的类型,只能读容器中的元素 |
reverse_iterator | 指向元素的逆向迭代器的类型,用于逆序寻址元素 |
const_reverse_iterator | 指向元素的常量逆序迭代器的类型,只能用于逆序读取容器中的元素 |
difference_type | 存储两个迭代器插值的有符号整型 |
value_type | 元素类型 |
reference | 元素的左值类型,等价于value_type& |
const_reference | 元素的常量左值类型,等价于value_type& |
size_type | 无符号整型,用于计算容器中的元素个数,也可用于对除list外的顺序容器进行检索 |
2.1.3访问元素
使用形式 | 形式参数 | 返回值 | 备注 |
c.back() | 无 | 容器最后一个元素的引用 | 若容器为空,则该操作的行为没有定义 |
c.front() | 无 | 容器第一个元素的引用 | 若容器为空,则该操作的行为没有定义 |
c[index] | index | 返回下标为index的元素的引用 | list容器无此操作;若下标越界,则该操作的行为没有定义 |
c.at(index) | index | 返回下标为index的元素的引用 | list容器无此操作;若下标越界,则该操作的行为没有定义 |
使用形式 | 返回值 | 备注 |
c.begin() | 迭代器指向容器c中的第一个元素 | 此表的每一个操作都有两个版本,一个是const成员,一个是非const成员;若容器c为const对象,则这些操作返回的迭代器的类型是带const_前缀的类型(只读迭代器),否则返回读写迭代器。 |
c.end() | 迭代器指向容器c中的最后一个元素的下一个位置 | |
c.rbegin() | 逆向迭代器指向容器c中最后一个元素 | |
c.rend() | 逆向迭代器指向容器中第一个元素的前一个位置 |
2.1.4增加元素
使用形式 | 形式参数 | 返回值 | 操作效果 |
c.insert(iter,t) | iter为迭代器,t为元素值 | 指向新插入元素的迭代器 | 在iter所指元素之前插入值为t的元素 |
c.insert(iter,n,t) | iter为迭代器,t为元素值 | 无 | 在iter所指元素之前插入n个值位t的元素 |
c.insert(iter,b,e) | iter,b,e均为迭代器 | 无 | 在iter所指元素之前插入[b,e)之内的元素 |
c.push_back(t) | t为元素值 | 无 | 在c的尾端增加值为t的元素 |
c.push_front(t) | t为元素值 | 无 | 在c的头端增加值为t的元素 (注:vector没有push_front(t)用法) |
2.1.5删除元素
使用形式 | 形式参数 | 返回值 | 操作效果 | 备注 |
c.clear() | 无 | 无 | 删除容器中的所有元素 | |
c.erase(iter) | iter为迭代器 | 迭代器指向被删除元素的下一元素 | 删除iter所指向的元素 | 若iter==c.end(),则该操作的行为没有定义 |
c.erase(b,e) | b,e为迭代器 | 迭代器指向被删除元素段的下一元素 | 删除[b,e)之内的所有元素 | |
c.pop_back() | 无 | 无 | 删除容器中的最后一个元素 | 若容器为空,则该操作的行为没有定义 |
c.pop_front() | 无 | 无 | 删除容器中的第一个元素 | 若容器为空,则该操作的行为没有定义 (注:vector没有push_front(t)用法) |
2.1.6容器的比较
比较操作 | 比较结果 |
== | 若两个容器中的元素个数相同且对应位置上的每个元素都相同,则比较结果为true,否则为false |
!= | 与==相反 |
< <= > >= | 若一个容器中的所有元素与另一容器中头一段元素相等,则较短的容器小于另一容器; 否则,两个容器第一对不相等的比较结果就是容器的比较结果 |
2.1.7有关容器大小的操作
使用形式 | 形式参数 | 返回值 | 操作效果 |
c.empty() | 无 | 若容器为空,则返回true; 否则返回false | |
c.size() | 无 | 返回容器中目前所存放的元素的数目,类型为C::size_type | |
c.max_size() | 无 | 返回容器中可存放元素的最大数目,类型为C::size_type | |
c.resize() | n为元素数目 | 无 | 将容器重新调整为可存放n个元素;若n<c.size(),则删除多余元素,否则,在尾端增加相应数目的新元素,新元素均采用值初始化 |
c.resize(n,t) | n为元素数目 | 无 | 新增元素取值为t,其余同c.resize(n) |
2.1.8容器的赋值与交换
使用形式 | 形式参数 | 操作效果 | 备注 |
c1=c2 | c2为容器 | 首先删除c1中的所有元素,然后将才中的元素复制给c1 | c1和c2必须是同类型容器且其元素类型也必须相同 |
c.assign(b,e) | b,e为一对迭代器 | 首先删除c中所有元素,然后将迭代器[b,e)之内的元素复制到c中 | b和e不能指向c中的元素,[b,e)之内的元素不必与c的元素类型相同,只需类型兼容即可 |
c.assign(n,t) | n为元素数目,t为元素值 | 首先删除c中的所有元素,然后在c中存放n个值为t的元素 | |
c.swap(c2) | c2为容器 | 交换c1和c2的所有元素 | c1和c2必须是同类型容器且其元素类型也必须相同 |
2.2有序关联容器
- set
- multiset
- map
- multimap
2.2.1pair类型
pair类型是一个模板类,在头文件utility中定义。一个pair对象包含两个公有数据成员:first和second。
使用形式 | 说明 |
pair<T1,T2>p | 创建空的pair对象p,p的两个数据成员类型分别为T1,T2,均采用值初始化 |
pair<T1,T2>p(v1,v2) | 创建pair对象,p的两个数据成员的类型分别为T1,T2,成员first初始化为v1,成员second初始化为v2 |
make_pair(v1,v2) | 标准库函数,使用值v1,v2创建pair对象 |
使用形式 | 说明 | 备注 |
p1<p2 | 若p1.first<p2.first或者!(p1.first<p2.first)&&p1.second<p2.second,则比较结果为true,否则为false | pair对象的比较使用其元素类型提供的相应比较操作 |
p1==p2 | 若p1.first==p2.first&&p1.second==p2.second,则比较结果为true,否则为false |
2.2.2map容器
map容器是键值对的集合,通常称为关联数组,通过键来访问值。所使用的键类型必须提供<操作符,若是类类型则要重载<操作符
函数使用形式 | 说明 |
map<K,T>m | 创建空的map容器m,其键类型为K,值类型为T |
map<K,T>m(mx) | 创建map容器m作为mx的副本,m和mx的键值对类型必须相同 |
map<K,T>m(b,e) | 创建map容器,并用迭代器[b,e)范围之内的元素副本对m进行初始化 |
类型别名 | 说明 |
key_type | 元素(pair对象)中键的类型 |
mapped_type | 元素中键所关联的值的类型 |
value_type | 元素的类型,是一个pair类型,其中first成员的类型为const map<K,T>::key_type,second成员的类型为map<K,T>::mapped_type |
访问map容器中的元素,可以使用下标访问容器,下标是作为键使用,不一定要是整型,如果该元素存在,则返回元素中键所对应的值,如果指定的元素不存在,将会导致在容器中增加一个新元素,该元素的键值即为给定的下标值,元素的值采用值初始化。
注:map容器下标操作的返回值类型为mapped_type类型,容器的迭代器引用的返回值类型是value_type类型。
使用形式 | 形式参数 | 返回值 | 操作效果 |
m.insert(e) | e为元素值,一个pair对象 | 一个pair对象,其first成员是指向被插入元素的迭代器,second成员是一个bool对象,表示是否插入了元素 | 若键e.first不在容器m中,则插入元素e,否则m保持不变 |
m.insert(iter,e) | iter为迭代器,表示搜索新元素存储位置的起点,e为元素值 | 一个迭代器,指向键为e.first的元素 | 在iter所指元素之后插入元素e,若键e.first已在容器m中,则m保持不变 |
m.insert(begin,end) | begin,end均为迭代器,表示要插入的元素的范围 | 无 | 将[begin,end)范围内的元素插入m中,若某元素的键已在m中,则不插入该元素 |
使用形式 | 形式参数 | 返回值 |
m.find(k) | k为要查找的键 | 若容器m中存在与k对应的元素,则返回指向该元素的迭代器;否则返回指向m中最后一个元素的下一位置的迭代器 |
m.count(k) | k为要查找的键 | k在容器m中出现的次数 |
使用形式 | 形式参数 | 返回值 | 操作效果 | 备注 |
m.erase(k) | k为要删除元素的键 | 被删除元素的个数,其类型为map容器中定义的size_type | 若容器m中存在键k的元素,则删除该元素 | 若返回值为0,表示要删除的元素不存在 |
m.erase(iter) | iter为指向要删除元素的迭代器 | 无 | 删除iter所指向的元素 | 若iter==m.end(),则该操作的行为没有定义 |
m.erase(b,e) | b,e为迭代器 | 无 | 删除[b,e)之内的元素 | 要求b>=e,若b==e,则不删除任何元素; |
其他函数:
- max_size()
2.2.3multimap容器
与map容器的区别:
1)键可以重复,即可以有多个元素包含相同的键,因此multimap不支持下标操作
2)insert操作每调用一次都会增加新的元素,键相同的元素相邻存放
3)以键值为参数的erase操作删除该键所关联的第一个元素,并返回被删除元素的数目
4)count操作返回的迭代器指向被查找键相关联的第一个元素
5)find操作返回的迭代器指向与被查找键相关联的第一个元素
使用形式 | 说明 | 备注 |
m.lower_bound(k) | 返回一个迭代器,指向容器m中第一个键>=k的元素 | 若键k不在容器中,则两个操作返回的迭代器相同:都指向k应该插入的位置 |
m.upper_bound(k) | 返回一个迭代器,指向容器m中第一个键<k的元素 | |
m.equal_range(k) | 返回一对迭代器的pair对象,其中first==m.lower_bound(k),second==m.upper_bound(k) |
2.2.4set容器
特性:set容器中的元素就是键本身,set容器中的元素不能重复
与map容器的区别:
1)不支持下标操作
2)没有定义mapped_type类型
3)定义的value_type类型不是pair类型,而是与key_type相同
2.2.5multiset容器
与set容器的区别:键可以重复
2.3有序关联容器
- unordered_set //hast_set
- unordered_multiset //hash_multiset
- unordered_map //hash_map
- unordered_multimap //hash_multimap
2.4容器适配器
类名 | 说明 | 所在头文件 | 底层实现容器 | 方法 | 支持的操作符 |
stack | 堆栈,LIFO | <stack> | deque(default) list vector | push(item) pop() top() empty() size() | 每种容器都支持< <= > >= == !=,前提是元素类型要支持==和<操作。每两个适配器对象的比较由元素的依次比较而实现,结果取决于两个适配器中第一对不相等的元素。 |
queue | 队列,FIFO | <queue> | deque(default) list | push(item) pop() front() back() empty() size() | |
priority_queue | 优先级队列,元素按优先级从高到低排列,使用元素的<操作确定优先级 | <queue> | vector(default) | 见注4) |
注:
1)每种适配器都定义了三种类型别名:
- size_type表示适配器对象大小的类型
- value_type元素类型
- container_type基础容器的类型
2)每种适配器都定义了两个构造函数:
- 不带参数的构造函数,用于创建空的适配器对象
- 带一个容器参数的构造函数,用于根据基础容器内容创建适配器对象并进行初始化
3)priority_queue适配器支持的操作
- push(item),按优先级顺序将值为item的新元素插入到队列中适当位置,无返回值。实现方式:首先调用基础容器的push_back操作,然后调用堆排序算法push_heap对元素进行重新排列
- pop(),删除队首元素,无返回值。实现方式:首先调用堆操作算法pop_heap删除堆顶元素,然后调用基础容器的pop_back操作
- top(),返回队首元素的值
- empty()
- size()
三、容器举例
3.1array
array是顺序容器的一种,跟数组很类似,array也是在栈上分配连续的内存,array的大小是不可改变的,定义array对象时就需要指明大小,所以只能修改array中的元素,不能向array中插入元素或从array中删除元素
3.1.1声明、初始化、赋值、交换
//第二个参数只能是整型常量,不能是变量
array<int, 10>arr1; //定义一个array对象arr1,arr1中的元素是不确定的
arr1.fill(5); //fill(value)方法可以将arr1的元素全赋值为相同的值value
array<int, 10>arr2 = { 0 }; //定义一个array对象arr2,arr2中的元素全为0,剩余的空位自动补零
array<int, 10>arr3 = { 1,2,3,4,5,6,7,8,9 }; //定义一个array对象arr3,arr3中的元素为1 2 3 4 5 6 7 8 9 0
array<int, 10>arr4 = arr2; //array对象可以直接赋值,前提是两个对象的元素类型和个数相同
arr4 = arr3; //legal
arr4 = { 1,2,3 }; //legal
swap(arr2, arr3); //标准库方法
arr2.swap(arr3); //array对象方法
3.1.2遍历
//跟数组一样遍历
for (int i = 0; i < arr.size(); i++)
{
cout << arr[i] << " ";
cout << arr.at(i) << " ";
}
cout << endl;
//利用迭代器遍历
//array<int,10>::iterator it;
for (auto it = arr.begin(); it != arr.end(); it++)
cout << *it << " ";
cout << endl;
//for-each遍历
for (auto i : arr)
cout << i << " ";
cout << endl;
3.2vector
- vector是顺序容器的一种,跟数组和array类似。vector是在堆上动态分配内存,大小可以自动调整。
- 不会原地扩充,而是重新开辟一块两倍大的内存,然后把原先的元素拷贝到新的内存中。
3.2.1声明、初始化、赋值、交换
vector<int> vec1; //定义一个空的vector对象vec1
//vec2/3/4是vec1的一个副本,若vec1.size()>vec2/3/4.size()则赋值后vec2/3/4.size()被扩充为vec1.size()
//前提是两个vector对象的元素类型要相同
vector<int>vec2(vec1); //用vector对象初始化另一个vector对象
vector<int>vec3(vec1.begin(), vec1.end()); //用vector对象的部分元素初始化另一个vector对象
vector<int>vec4 = vec1; //将vector对象赋值给另一个vector对象
int length = 10;
vector<int> vec5(length); //arr2包含length个0元素
vector<int> vec6(length, 3); //temp中包含10个3
int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
vector<int>vec7(arr,arr+10); //可以将数组的部分连续元素的首尾地址传给vector对象
swap(arr1, arr2);
arr1.swap(arr2);
3.2.2遍历
//像数组一样遍历
for (int i = 0; i < vec.size(); i++) //size()返回vec中的元素个数
{
cout << vec[i] << " "; //operator [],不做边界检查,可以越界,访问效率更高
cout << vec.at(i) << " "; //at(),访问越界会抛出异常,但访问效率不如[]
}
cout << endl;
//利用迭代器遍历
//vector<int>::iterator it;
for (auto it = vec.begin(); it != vec.end(); it++)
cout << *it << " ";
cout << endl;
//for-each遍历
for (auto i : vec)
cout << i << " ";
cout << endl;
3.2.3增加元素
- vec.push_back(ele);
3.2.4删除元素
- vec.pop_back();
- vec.clear(); //清除整个vector
- vec.erase(ite); //清除迭代器ite指向的元素
3.2.5其他方法
- empty()
3.3deque
3.4list
- splice();
3.5forward_list
- front()
- push_front()
- max_size()
- sort()
3.5deque
- push_back()
- push_front()
- size()
- max_size()
- front()
- back()
3.6set
set的特性:set是关联容器,元素具有唯一性,而且有序
3.5.1.定义和声明
using namespace std;
set<int>s;
3.7multiset
- insert()
- max_size()
- size()
- find()
3.8map
同上
3.9unordered_set
- bucket_count()
- load_factor()
- max_bucket_count()
- max_load_factor()
- bucket_size()
- max_size()
- find()
3.10unordered_map()
- size()
- max_size()
- find()
四、算法
- 算法使用迭代器在容器上进行操作。
- 不修改序列的算法,在头文件algorithm中定义
- 变更序列的算法,在头文件algorithm中定义
- 排序及相关算法,在头文件algorithm中定义
- 泛化算术算法,在头文件numeric中定义
五、仿函数
- 仿函数:相当于函数指针
- // TODO
六、分配器
// TODO
参考博客:
1.https://blog.youkuaiyun.com/SENLINZM/article/details/38682233