stl 表格
迭代器类别
STL 标准库为每一种标准容器定义了一种迭代器类型,这意味着,不同容器的迭代器也不同,其功能强弱也有所不同。
容器的迭代器的功能强弱,决定了该容器是否支持 STL 中的某种算法。
常用的迭代器按功能强弱分为输入迭代器、输出迭代器、前向迭代器、双向迭代器、随机访问迭代器 5 种。本节主要介绍后面的这 3 种迭代器。
输入迭代器和输出迭代器比较特殊,它们不是把数组或容器当做操作对象,而是把输入流/输出流作为操作对象。有关这 2 个迭代器,我们会在后续章节做详细介绍。
 1) 前向迭代器(forward iterator)
假设 p 是一个前向迭代器,则 p 支持 ++p,p++,*p 操作,还可以被复制或赋值,可以用 == 和 != 运算符进行比较。此外,两个正向迭代器可以互相赋值。
2) 双向迭代器(bidirectional iterator)
双向迭代器具有正向迭代器的全部功能,除此之外,假设 p 是一个双向迭代器,则还可以进行 --p 或者 p-- 操作(即一次向后移动一个位置)。
3) 随机访问迭代器(random access iterator)
随机访问迭代器具有双向迭代器的全部功能。除此之外,假设 p 是一个随机访问迭代器,i 是一个整型变量或常量,则 p 还支持以下操作:
- p+=i:使得 p 往后移动 i 个元素。
- p-=i:使得 p 往前移动 i 个元素。
- p+i:返回 p 后面第 i 个元素的迭代器。
- p-i:返回 p 前面第 i 个元素的迭代器。
- p[i]:返回 p 后面第 i 个元素的引用。
此外,两个随机访问迭代器 p1、p2 还可以用 <、>、<=、>= 运算符进行比较。另外,表达式 p2-p1 也是有定义的,其返回值表示 p2 所指向元素和 p1 所指向元素的序号之差(也可以说是 p2 和 p1 之间的元素个数减一)。
表 1 所示,是 C++ 11 标准中不同容器指定使用的迭代器类型。
| 容器 | 对应的迭代器类型 | 
|---|---|
| array | 随机访问迭代器 | 
| vector | 随机访问迭代器 | 
| deque | 随机访问迭代器 | 
| list | 双向迭代器 | 
| set / multiset | 双向迭代器 | 
| map / multimap | 双向迭代器 | 
| forward_list | 前向迭代器 | 
| unordered_map / unordered_multimap | 前向迭代器 | 
| unordered_set / unordered_multiset | 前向迭代器 | 
| stack | 不支持迭代器 | 
| queue | 不支持迭代器 | 
注意,容器适配器 stack 和 queue 没有迭代器,它们包含有一些成员函数,可以用来对元素进行访问。
迭代器的定义方式
尽管不同容器对应着不同类别的迭代器,但这些迭代器有着较为统一的定义方式,具体分为 4 种,如表 1 所示。
| 迭代器定义方式 | 具体格式 | 
|---|---|
| 正向迭代器 | 容器类名::iterator 迭代器名; | 
| 常量正向迭代器 | 容器类名::const_iterator 迭代器名; | 
| 反向迭代器 | 容器类名::reverse_iterator 迭代器名; | 
| 常量反向迭代器 | 容器类名::const_reverse_iterator 迭代器名; | 
值得一提的是,表 2 中的反向迭代器全称为 "反向迭代器适配器",后续章节会做详细讲解,这里读者只需要知道其用法即可。
通过定义以上几种迭代器,就可以读取它指向的元素,*迭代器名就表示迭代器指向的元素。其中,常量迭代器和非常量迭代器的分别在于,通过非常量迭代器还能修改其指向的元素。另外,反向迭代器和正向迭代器的区别在于:
- 对正向迭代器进行 ++ 操作时,迭代器会指向容器中的后一个元素;
- 而对反向迭代器进行 ++ 操作时,迭代器会指向容器中的前一个元素。
注意,以上 4 种定义迭代器的方式,并不是每个容器都适用。有一部分容器同时支持以上 4 种方式,比如 array、deque、vector;而有些容器只支持其中部分的定义方式,例如 forward_list 容器只支持定义正向迭代器,不支持定义反向迭代器。
queue 操作 queue 和 stack 有一些成员函数相似,但在一些情况下,工作方式有些不同: front():返回 queue 中第一个元素的引用。如果 queue 是常量,就返回一个常引用;如果 queue 为空,返回值是未定义的。 back():返回 queue 中最后一个元素的引用。如果 queue 是常量,就返回一个常引用;如果 queue 为空,返回值是未定义的。 push(const T& obj):在 queue 的尾部添加一个元素的副本。这是通过调用底层容器的成员函数 push_back() 来完成的。 push(T&& obj):以移动的方式在 queue 的尾部添加元素。这是通过调用底层容器的具有右值引用参数的成员函数 push_back() 来完成的。 pop():删除 queue 中的第一个元素。 size():返回 queue 中元素的个数。 empty():如果 queue 中没有元素的话,返回 true。 emplace():用传给 emplace() 的参数调用 T 的构造函数,在 queue 的尾部生成对象。 swap(queue<T> &other_q):将当前 queue 中的元素和参数 queue 中的元素交换。它们需要包含相同类型的元素。也可以调用全局函数模板 swap() 来完成同样的操作。 queue<T> 模板定义了拷贝和移动版的 operator=(),对于所保存元素类型相同的 queue 对象,它们有一整套的比较运算符,这些运算符的工作方式和 stack 容器相同。 和 stack 一样,queue 也没有迭代器。访问元素的唯一方式是遍历容器内容,并移除访问过的每一个元素。例如:
容器中常见的函数成员
序列容器包含一些相同的成员函数,它们的功能也相同,本教程会在某个容器的上下文中详细介绍下面的每个函数,但对于每种类型的容器不会重复介绍它们的细节。
表 2 展示了 array、vector 和 deque 容器的函数成员,它们中至少有两个容器实现了同样的函数成员。
| 函数成员 | 函数功能 | array<T,N> | vector<T> | deque<T> | 
|---|---|---|---|---|
| begin() | 返回指向容器中第一个元素的迭代器。 | 是 | 是 | 是 | 
| end() | 返回指向容器最后一个元素所在位置后一个位置的迭代器,通常和 begin() 结合使用。 | 是 | 是 | 是 | 
| rbegin() | 返回指向最后一个元素的迭代器。 | 是 | 是 | 是 | 
| rend() | 返回指向第一个元素所在位置前一个位置的迭代器。 | 是 | 是 | 是 | 
| cbegin() | 和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 | 是 | 是 | 是 | 
| cend() | 和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 | 是 | 是 | 是 | 
| crbegin() | 和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 | 是 | 是 | 是 | 
| crend() | 和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 | 是 | 是 | 是 | 
| assign() | 用新元素替换原有内容。 | - | 是 | 是 | 
| operator=() | 复制同类型容器的元素,或者用初始化列表替换现有内容。 | 是 | 是 | 是 | 
| size() | 返回实际元素个数。 | 是 | 是 | 是 | 
| max_size() | 返回元素个数的最大值。这通常是一个很大的值,一般是 232-1,所以我们很少会用到这个函数。 | 是 | 是 | 是 | 
| capacity() | 返回当前容量。 | - | 是 | - | 
| empty() | 判断容器中是否有元素,若无元素,则返回 true;反之,返回 false。 | 是 | 是 | 是 | 
| resize() | 改变实际元素的个数。 | - | 是 | 是 | 
| shrink _to_fit() | 将内存减少到等于当前元素实际所使用的大小。 | - | 是 | 是 | 
| front() | 返回第一个元素的引用。 | 是 | 是 | 是 | 
| back() | 返回最后一个元素的引用。 | 是 | 是 | 是 | 
| operator[]() | 使用索引访问元素。 | 是 | 是 | 是 | 
| at() | 使用经过边界检査的索引访问元素。 | 是 | 是 | 是 | 
| push_back() | 在序列的尾部添加一个元素。 | - | 是 | 是 | 
| insert() | 在指定的位置插入一个或多个元素。 | - | 是 | 是 | 
| emplace() | 在指定的位置直接生成一个元素。 | - | 是 | 是 | 
| emplace_back() | 在序列尾部生成一个元素。 | - | 是 | 是 | 
| pop_back() | 移出序列尾部的元素。 | - | 是 | 是 | 
| erase() | 移出一个元素或一段元素。 | - | 是 | 是 | 
| clear() | 移出所有的元素,容器大小变为 0。 | - | 是 | 是 | 
| swap() | 交换两个容器的所有元素。 | 是 | 是 | 是 | 
| data() | 返回指向容器中第一个元素的指针。 | 是 | 是 | - | 
列表中 - 表明对应的容器并没有定义这个函数。
list 和 forward_list 容器彼此非常相似,forward_list 中包含了 list 的大部分成员函数,而未包含那些需要反向遍历的函数。表 3 展示了 list 和 forward_list 的函数成员。
| 函数成员 | 函数功能 | list<T> | forward_list<T> | 
|---|---|---|---|
| begin() | 返回指向容器中第一个元素的迭代器。 | 是 | 是 | 
| end() | 返回指向容器最后一个元素所在位置后一个位置的迭代器。 | 是 | 是 | 
| rbegin() | 返回指向最后一个元素的迭代器。 | 是 | - | 
| rend() | 返回指向第一个元素所在位置前一个位置的迭代器。 | 是 | - | 
| cbegin() | 和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 | 是 | 是 | 
| before_begin() | 返回指向第一个元素前一个位置的迭代器。 | - | 是 | 
| cbefore_begin() | 和 before_begin() 功能相同,只不过在其基础上,增加了 const 属性,即不能用该指针修改元素的值。 | - | 是 | 
| cend() | 和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 | 是 | 是 | 
| crbegin() | 和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 | 是 | - | 
| crend() | 和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 | 是 | - | 
| assign() | 用新元素替换原有内容。 | 是 | 是 | 
| operator=() | 复制同类型容器的元素,或者用初始化列表替换现有内容。 | 是 | 是 | 
| size() | 返回实际元素个数。 | 是 | - | 
| max_size() | 返回元素个数的最大值,这通常是一个很大的值,一般是 232-1,所以我们很少会用到这个函数。 | 是 | 是 | 
| resize() | 改变实际元素的个数。 | 是 | 是 | 
| empty() | 判断容器中是否有元素,若无元素,则返回 true;反之,返回 false。 | 是 | 是 | 
| front() | 返回容器中第一个元素的引用。 | 是 | 是 | 
| back() | 返回容器中最后一个元素的引用。 | 是 | - | 
| push_back() | 在序列的尾部添加一个元素。 | 是 | - | 
| push_front() | 在序列的起始位置添加一个元素。 | 是 | 是 | 
| emplace() | 在指定位置直接生成一个元素。 | 是 | - | 
| emplace_after() | 在指定位置的后面直接生成一个元素。 | - | 是 | 
| emplace_back() | 在序列尾部生成一个元素。 | 是 | - | 
| cmplacc_front() | 在序列的起始位生成一个元索。 | 是 | 是 | 
| insert() | 在指定的位置插入一个或多个元素。 | 是 | - | 
| insert_after() | 在指定位置的后面插入一个或多个元素。 | - | 是 | 
| pop_back() | 移除序列尾部的元素。 | 是 | - | 
| pop_front() | 移除序列头部的元素。 | 是 | 是 | 
| reverse() | 反转容器中某一段的元素。 | 是 | 是 | 
| erase() | 移除指定位置的一个元素或一段元素。 | 是 | - | 
| erase_after() | 移除指定位置后面的一个元素或一段元素。 | - | 是 | 
| remove() | 移除所有和参数匹配的元素。 | 是 | 是 | 
| remove_if() | 移除满足一元函数条件的所有元素。 | 是 | 是 | 
| unique() | 移除所有连续重复的元素。 | 是 | 是 | 
| clear() | 移除所有的元素,容器大小变为 0。 | 是 | 是 | 
| swap() | 交换两个容器的所有元素。 | 是 | 是 | 
| sort() | 对元素进行排序。 | 是 | 是 | 
| merge() | 合并两个有序容器。 | 是 | 是 | 
| splice() | 移动指定位置前面的所有元素到另一个同类型的 list 中。 | 是 | - | 
| splice_after() | 移动指定位置后面的所有元素到另一个同类型的 list 中。 | - | 是 | 

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号