- Iterator 迭代器
- 常见容器的迭代器
- Auxiliary Iterator Functions 辅助迭代器函数
- Reverse Iterators 反向迭代器
- Insert Iterators 插入迭代器
- 流迭代器(Stream Iterators)
- STL 内建仿函数
- functor adapters binders
- Binders(绑定器)
Iterator 迭代器
Iterator(迭代器)模式又称 Cursor(游标)模式,用于提供一种方法顺序访问一个
聚合对象中各个元素, 而又不需暴露该对象的内部表示。
Iterator 模式是运用于聚合对象的一种模式,通过运用该模式,使得我们可以在不知道
对象内部表示的情况下,按照一定顺序(由 iterator 提供的方法)访问聚合对象中的各
个元素。
能够让迭代器与算法不干扰的相互发展,最后又能无间隙的粘合起来;
重载了 *,++,==,!=,= 运算符。用以操作复杂的数据结构
容器提供迭代器,算法使用迭代器;
STL 迭代器主要分为以下几类:
输入迭代器(Input Iterators):只能向前移动,每次只能读取一次元素。
| 操作 | 说明 | 示例代码 |
|------------|----------------------------------------------|--------------------------------------------------------------|
| `*it` | 解引用迭代器,获取其指向的元素。 | `std::istream_iterator<int> input_iter(std::cin); int value = *input_iter;` |
| `++it` | 将迭代器向前移动一个位置。 | `++input_iter;` |
|`it++` | 将迭代器向前移动一个位置,并返回原位置。 | `input_iter++;` |
| `it1 == it2` | 比较两个输入迭代器是否相等。 | `if (input_iter1 == input_iter2) { ... }` |
| `it1 != it2` | 比较两个输入迭代器是否不相等。 | `if (input_iter1 != input_iter2) { ... }` |
输出迭代器(Output Iterators):只能向前移动,每次只能写入一次元素。
| 操作 | 说明 | 示例代码 |
|------------|----------------------------------------------|--------------------------------------------------------------|
| `*it = value` | 将值写入迭代器指向的位置。 | `std::ostream_iterator<int> output_iter(std::cout, " "); *output_iter = 42;` |
| `++it` | 将迭代器向前移动一个位置。传回新位置 | `++output_iter;` |
|`it++` | 将迭代器向前移动一个位置,并返回原位置。 | `output_iter++;` |
前向迭代器(Forward Iterators):可以多次读写同一个元素,但只能向前移动。
| 操作 | 说明 | 示例代码 |
|------------|----------------------------------------------|--------------------------------------------------------------|
| `*it` | 解引用迭代器,获取其指向的元素。 | `std::forward_list<int>::iterator it = flist.begin(); int value = *it;` |
| `*it = value` | 将值写入迭代器指向的位置。 | `*it = 42;` |
| `++it` | 将迭代器向前移动一个位置。 | `++it;` |
|`it++` | 将迭代器向前移动一个位置,并返回原位置。 | `it++;` |
| `it1 == it2` | 比较两个前向迭代器是否相等。 | `if (it1 == it2) { ... }` |
| `it1 != it2` | 比较两个前向迭代器是否不相等。 | `if (it1 != it2) { ... }` |
双向迭代器(Bidirectional Iterators):在前向迭代器的基础上,增加了向后移动的能力。
| 操作 | 说明 | 示例代码 |
|------------|----------------------------------------------|--------------------------------------------------------------|
| `*it` | 解引用迭代器,获取其指向的元素。 | `std::list<int>::iterator it = lst.begin(); int value = *it;` |
| `*it = value` | 将值写入迭代器指向的位置。 | `*it = 42;` |
| `++it` | 将迭代器向前移动一个位置。 | `++it;` |
|`it++` | 将迭代器向前移动一个位置,并返回原位置。 | `it++;` |
| `--it` | 将迭代器向后移动一个位置。 | `--it;` |
|`it--` | 将迭代器向后移动一个位置,并返回原位置。 | `it--;` |
| `it1 == it2` | 比较两个双向迭代器是否相等。 | `if (it1 == it2) { ... }` |
| `it1 != it2` | 比较两个双向迭代器是否不相等。 | `if (it1 != it2) { ... }` |
随机访问迭代器(Random Access Iterators):在双向迭代器的基础上,增加了随机访问的能力,可以进行指针算术运算。
| 操作 | 说明 | 示例代码 |
|------------|----------------------------------------------|--------------------------------------------------------------|
| `*it` | 解引用迭代器,获取其指向的元素。 | `std::vector<int>::iterator it = vec.begin(); int value = *it;` |
| `*it = value` | 将值写入迭代器指向的位置。 | `*it = 42;` |
| `++it` | 将迭代器向前移动一个位置。 | `++it;` |
|`it++` | 将迭代器向前移动一个位置,并返回原位置。 | `it++;` |
| `--it` | 将迭代器向后移动一个位置。 | `--it;` |
|`it--` | 将迭代器向后移动一个位置,并返回原位置。 | `it--;` |
| `it += n` | 将迭代器向前移动 n 个位置。 | `it += 3;` |
| `it -= n` | 将迭代器向后移动 n 个位置。 | `it -= 2;` |
| `it + n` | 返回指向 it 后面第 n 个位置的迭代器。 | `auto new_it = it + 5;` |
| `it - n` | 返回指向 it 前面第 n 个位置的迭代器。 | `auto new_it = it - 3;` |
| `it1 - it2` | 返回两个迭代器之间的距离。 | `auto distance = it1 - it2;` |
| `it1 < it2` | 比较两个迭代器,判断 it1 是否在 it2 之前。 | `if (it1 < it2) { ... }` |
| `it1 > it2` | 比较两个迭代器,判断 it1 是否在 it2 之后。 | `if (it1 > it2) { ... }` |
| `it1 <= it2` | 比较两个迭代器,判断 it1 是否在 it2 之前或相等。 | `if (it1 <= it2) { ... }` |
| `it1 >= it2` | 比较两个迭代器,判断 it1 是否在 it2 之后或相等。 | `if (it1 >= it2) { ... }` |
| `it1 == it2` | 比较两个随机访问迭代器是否相等。 | `if (it1 == it2) { ... }` |
| `it1 != it2` | 比较两个随机访问迭代器是否不相等。 | `if (it1 != it2) { ... }` |
常见容器的迭代器
| 容器 | 支持的迭代器类别 |
|-----------------|------------------|
| `vector` | 随机访问 |
| `deque` | 随机访问 |
| `list` | 双向 |
| `set` | 双向 |
| `multiset` | 双向 |
| `map` | 双向 |
| `multimap` | 双向 |
| `stack` | 不支持 |
| `queue` | 不支持 |
| `priority_queue`| 不支持 |
Auxiliary Iterator Functions 辅助迭代器函数
STL 提供了额外的 5 个函数,advance(),next(), prev(), distance(), iter_swap(),
前 4 个函数,是用于非 (随机存取迭代器) random-access Iterator,可以实现多步跨越。
最后一个函数用于交换两个 iterator。
| 函数原型 | 描述 |
|-------------------------------------------------------------------------|----------------------------------------------------------------------|
| `void advance (InputIterator& pos, Dist n)` | 将迭代器 `pos` 向前(或向后,如果 `n` 为负)移动 `n` 个位置。 |
| `ForwardIterator next (ForwardIterator pos)` | 返回一个指向 `pos` 后一个位置的迭代器。 |
| `ForwardIterator next (ForwardIterator pos, Dist n)` | 返回一个指向 `pos` 后 `n` 个位置的迭代器。 |
| `BidirectionalIterator prev (BidirectionalIterator pos)` | 返回一个指向 `pos` 前一个位置的迭代器。 |
| `BidirectionalIterator prev (BidirectionalIterator pos, Dist n)` | 返回一个指向 `pos` 前 `n` 个位置的迭代器。 |
| `Dist distance (InputIterator pos1, InputIterator pos2)` | 计算从 `pos1` 到 `pos2` 的距离(元素个数)。 |
| `void iter_swap (ForwardIterator1 pos1, ForwardIterator2 pos2)` | 交换 `pos1` 和 `pos2` 指向的元素的值。 |
#include <iostream>
#include <list>
#include <iterator>
int main() {
// 创建一个包含整数的链表
std::list<int> lst = {1, 2, 3, 4, 5};
// 测试 advance 函数
// advance 函数用于将迭代器向前或向后移动指定数量的位置
std::list<int>::iterator it = lst.begin(); // 获取链表的起始迭代器
std::advance(it, 2); // 将迭代器向前移动2个位置
std::cout << "After advance(it, 2): " << *it << std::endl; // 输出 3
// 测试 next 函数
// next 函数返回一个指向当前迭代器之后第n个元素的迭代器
std::list<int>::iterator nextIt = std::next(it); // 返回指向it之后第1个元素的迭代器
std::cout << "After next(it): " << *nextIt << std::endl; // 输出 4
nextIt = std::next(it, 2); // 返回指向it之后第2个元素的迭代器
std::cout << "After next(it, 2): " << *nextIt << std::endl; // 输出 5
// 测试 prev 函数
// prev 函数返回一个指向当前迭代器之前第n个元素的迭代器
std::list<int>::iterator prevIt = std::prev(it); // 返回指向it之前第1个元素的迭代器
std::cout << "After prev(it): " << *prevIt << std::endl; // 输出 2
prevIt = std::prev(it, 2); // 返回指向it之前第2个元素的迭代器
std::cout << "After prev(it, 2): " << *prevIt << std::endl; // 输出 1
// 测试 distance 函数
// distance 函数计算两个迭代器之间的距离
std::list<int>::iterator start = lst.begin(); // 获取链表的起始迭代器
std::list<int>::iterator end = lst.end(); // 获取链表的结束迭代器
std::cout << "Distance from start to end: " << std::distance(start, end) << std::endl; // 输出 5
// 测试 iter_swap 函数
// iter_swap 函数交换两个迭代器指向的元素
std::list<int>::iterator it1 = lst.begin(); // 获取链表的起始迭代器
std::list<int>::iterator it2 = std::next(lst.begin(), 2); // 获取链表的第3个元素的迭代器
std::iter_swap(it1, it2); // 交换it1和it2指向的元素
std::cout << "After iter_swap(it1, it2): ";
for (int i : lst) {
std::cout << i << " ";
}
std::cout << std::endl; // 输出 3 2 1 4 5
return 0;
}
Reverse Iterators 反向迭代器
反向迭代器(Reverse Iterators)是一种特殊的迭代器,用于以相反的顺序遍历容器中的元素。
在C++标准库中,许多容器(如std::vector、std::list、std::deque等)都支持反向迭代器。
反向迭代器通常通过容器的rbegin()和rend()方法来获取。
rbegin()返回指向容器最后一个元素的反向迭代器,而rend()返回指向容器第一个元素之前的反向迭代器。
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
// 使用反向迭代器遍历vector
for (auto rit = vec.rbegin(); rit != vec.rend(); ++rit) {
std::cout << *rit << " ";
}
std::cout << std::endl;
return 0;
}
Insert Iterators 插入迭代器
插入迭代器(Insert Iterators)是一种特殊的迭代器适配器,用于在容器的特定位置插入元素,而不是覆盖或替换现有元素。插入迭代器主要有三种类型:
back_insert_iterator:在容器的末尾插入元素。
front_insert_iterator:在容器的开头插入元素。
insert_iterator:在容器的指定位置插入元素。
这些插入迭代器通常与标准库的算法(如std::copy)一起使用,以便在复制元素时将它们插入到目标容器中。
示例
使用 back_insert_iterator
#include <iostream>
#include <vector>
#include <iterator>
int main() {
std::vector<int> source = {1, 2, 3, 4, 5};
std::vector<int> destination;
// 使用 back_insert_iterator 将 source 的元素插入到 destination 的末尾
std::copy(source.begin(), source.end(), std::back_inserter(destination));
// 输出 destination 的内容
for (int x : destination) {
std::cout << x << " ";
}
std::cout << std::endl;
return 0;
}
使用 front_insert_iterator
#include <iostream>
#include <deque>
#include <iterator>
int main() {
std::deque<int> source = {1, 2, 3, 4, 5};
std::deque<int> destination;
// 使用 front_insert_iterator 将 source 的元素插入到 destination 的开头
std::copy(source.begin(), source.end(), std::front_inserter(destination));
// 输出 destination 的内容
for (int x : destination) {
std::cout << x << " ";
}
std::cout << std::endl;
return 0;
}
使用 insert_iterator
#include <iostream>
#include <vector>
#include <iterator>
int main() {
std::vector<int> source = {1, 2, 3, 4, 5};
std::vector<int> destination = {10, 20, 30};
// 使用 insert_iterator 将 source 的元素插入到 destination 的指定位置
std::copy(source.begin(), source.end(), std::inserter(destination, destination.begin() + 1));
// 输出 destination 的内容
for (int x : destination) {
std::cout << x << " ";
}
std::cout << std::endl;
return 0;
}
流迭代器(Stream Iterators)
用于将输入输出流(如std::istream和std::ostream)与标准库算法和容器结合起来。流迭代器主要有两种类型:
istream_iterator:用于从输入流中读取数据。
ostream_iterator:用于向输出流中写入数据。
示例
使用 istream_iterator
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
int main() {
// 从标准输入流中读取整数,并存储到 vector 中
std::vector<int> vec((std::istream_iterator<int>(std::cin)), std::istream_iterator<int>());
// 输出 vector 的内容
std::copy(vec.begin(), vec.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
return 0;
}
使用 ostream_iterator
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
// 将 vector 的内容输出到标准输出流
std::copy(vec.begin(), vec.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
return 0;
}
结合使用 istream_iterator 和 ostream_iterator
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
int main() {
// 从标准输入流中读取整数,并存储到 vector 中
std::vector<int> vec((std::istream_iterator<int>(std::cin)), std::istream_iterator<int>());
// 将 vector 的内容输出到标准输出流
std::copy(vec.begin(), vec.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
return 0;
}
STL 内建仿函数
| 类别 | 仿函数名称 | 描述 |
|------------|------------------|------------------------------------------|
| 算术仿函数 | plus<T> | 加法仿函数,用于两个元素相加 |
| | minus<T> | 减法仿函数,用于两个元素相减 |
| | multiplies<T> | 乘法仿函数,用于两个元素相乘 |
| | divides<T> | 除法仿函数,用于两个元素相除 |
| | modulus<T> | 取模仿函数,用于两个元素取模 |
| | negate<T> | 取反仿函数,用于元素取反 |
| 比较仿函数 | equal_to<T> | 等于仿函数,用于判断两个元素是否相等 |
| | not_equal_to<T> | 不等于仿函数,用于判断两个元素是否不相等 |
| | greater<T> | 大于仿函数,用于判断一个元素是否大于另一个元素 |
| | less<T> | 小于仿函数,用于判断一个元素是否小于另一个元素 |
| | greater_equal<T> | 大于等于仿函数,用于判断一个元素是否大于或等于另一个元素 |
| | less_equal<T> | 小于等于仿函数,用于判断一个元素是否小于或等于另一个元素 |
| 逻辑仿函数 | logical_and<T> | 逻辑与仿函数,用于两个元素的逻辑与操作 |
| | logical_or<T> | 逻辑或仿函数,用于两个元素的逻辑或操作 |
| | logical_not<T> | 逻辑非仿函数,用于元素的逻辑非操作 |
functor adapters binders
Binders(绑定器)
绑定器用于将函数的部分参数绑定到特定的值,从而生成一个新的函数对象。
C++标准库提供了std::bind和std::placeholders来实现这一功能。
#include <iostream>
#include <functional>
using namespace std;
using namespace std::placeholders; // 引入占位符命名空间
class A{
public:
void print(int x,int y){
cout<<"x : "<<x<<endl;
cout<<"y : "<<y<<endl;
}
};
int main(){
A a;
auto f= bind(&A::print,a,1,2); //绑定对象a的print函数,并传入参数1和2
f(); //调用绑定函数
auto f1=bind(&A::print,_1,_2,_3);
f1(a,1,2); //调用绑定函数,传入参数a,1,2
auto f2=bind(&A::print,_1,100,200);
f2(a);
auto f3=bind(&A::print,a,_1,_2);
f3(55,66);
return 0;
}
#include <functional>
#include <algorithm>
#include <vector>
#include <iostream>
#include <string>
using namespace std;
using namespace std::placeholders;
class Person // 定义Person类
{
private:
string name; // 私有成员变量,存储人的名字
public:
Person (const string& n) : name(n) // 构造函数,初始化name成员变量
{
}
void print () const // 成员函数,打印名字
{
cout << name << endl;
}
void print2 (const string& prefix) const // 成员函数,打印带前缀的名字
{
cout << prefix << name << endl;
}
};
int main()
{
Person p("abc"); // 创建一个Person对象,名字为"abc"
auto mem = bind(&Person::print, p); // 使用bind绑定Person对象p的print成员函数
mem(); // 调用绑定后的函数对象,打印"abc"
vector<Person> vp = { // 创建一个Person对象的vector,包含三个Person对象
Person("Tick"),
Person("Trick"),
Person("Track")
};
for_each (vp.begin(), vp.end(), // 使用for_each算法遍历vector中的每个Person对象
bind(&Person::print, _1)); // 绑定每个Person对象的print成员函数,打印每个对象的名字
cout << endl; // 打印换行
for_each (vp.begin(), vp.end(), // 使用for_each算法遍历vector中的每个Person对象
bind(&Person::print2, _1, "Person: ")); // 绑定每个Person对象的print2成员函数,并传入前缀"Person: ",打印带前缀的名字
cout << endl; // 打印换行
bind(&Person::print2, _1, "This is: ")(Person("nico")); // 直接使用bind绑定Person::print2成员函数,并传入前缀"This is: ",然后立即调用,打印"This is: nico"
return 0;
}