STL 中的迭代器有以下几种:输入迭代器、输出迭代器、正向迭代器、双向迭代器、随机访问迭代器。
1. 输入迭代器:一次只能读取一个元素,只能向前移动,支持:++、==、!=、(只读)
2. 输出迭代器:一次只能写一个元素,只能向前移动,支持:++、==、!=、(只写)
3. 正向迭代器:一次可以读写元素,只能向前移动,支持++、==、!=、(读写)
4. 双向迭代器:一次可以读写元素,能够双向移动,支持++、–、==、!=、(读写)
5. 随机迭代器:一次可以读写一个元素,支持正向、反向、任意位置移动。支持:++、–、==、!=、*(读写)、+=、+ -、-=、[]等
#include <iostream> #include <vector> #include <deque> #include <forward_list> #include <list> #include <set> #include <unordered_set> #include <map> #include <unordered_map> using namespace std;
1. 容器支持的迭代器
算法使用的迭代器种类是不同的,比如,有些算法要求迭代器类型必须是随机访问迭代器,那么,你的容器提供的是双向迭代器,就用不了这种算法。
void test01() { // 1. vector 提供的迭代器是随机访问迭代器 vector<int>::iterator it1; it1 += 5; // 2. deque 提供的迭代器是随机访问迭代器 deque<int>::iterator it2; it2 += 5; // 3. forward_list 提供的是正向迭代器 forward_list<int>::iterator it3; // it3 += 5; // 语法报错 it3++; // it3--; // 语法报错 // 4. list 提供的是双向迭代器 list<int>::iterator it4; // it4 += 5; // 语法报错 it4++; it4--; // 5. set 提供的是双向迭代器 set<int>::const_iterator it5; // it5 += 5; // 语法错误 it5++; it5--; // 6. unordered_set 提供的是双向迭代器 unordered_set<int>::iterator it6; // it6 += 5; // 语法错误 it6++; it6--; // 7. map 容器提供的是双向迭代器 map<int, int>::iterator it7; // it7 += 5; // 语法错误 it7++; it7--; // 8. unordered_map 提供的是双向迭代器 unordered_map<int, int>::iterator it8; // it8+=5; it8++; it8--; }
2. 迭代器辅助函数
- advance 函数:向前或者向后移动某个容器的迭代器到某个位置
- distance 函数:用于计算两个迭代器之间相差元素的个数
- iter_swap 函数:交换两个迭代器指向的元素的值
void test02() { // 1. advance 函数:向前或者向后移动某个容器的迭代器到某个位置 vector<int> v = { 10, 20, 30, 40, 50 }; auto it1 = v.begin() + 3; list<int> l = { 10, 20, 30, 40, 50 }; auto it2 = l.begin(); //it2++; //it2++; //it2++; advance(it2, 3); // 2. distance 函数:用于计算两个迭代器之间相差元素的个数 // 参数为两个迭代器区间,一般这两个迭代器都指向同一个容器 distance(v.begin(), it1); // 3. iter_swap 函数:交换两个迭代器指向的元素的值 // iter_swap(v.begin(), it1); iter_swap(v.begin(), it2); for (auto val : v) cout << val << " "; cout << endl; } template<class T> ostream& operator<<(ostream& os, const vector<T>& vec) { for (auto v : vec) cout << v << " "; return os; } template<class T> ostream& operator<<(ostream& os, const deque<T>& vec) { for (auto v : vec) cout << v << " "; return os; }
3. 迭代器适配器
3.1 插入型迭代器
- 尾插型迭代器 back_inserter 支持的容器有 vector、deque、list 等有 push_back 函数的容器
- 头插迭代器 front_inserter 支持的容器有 deque、list、forward_list 等有 push_front 函数的容器
- 指定位置插入的迭代器 inserter 支持的容器有 vector、list 等有 insert 函数的容器
void test03() { vector<int> v = { 10, 20, 30 }; // 1. 尾插型迭代器(vector、deque、list) // back_inserter 函数可以获得某个容器的尾部插入迭代器 back_insert_iterator<vector<int>> it1 = back_inserter(v); // it1 叫做尾部插入迭代器,对该迭代器的赋值操作,将会导致元素插入到容器尾部 it1 = 100; *it1 = 200; cout << v << endl; // 注意:使用尾插迭代器,容器必须有 push_back 函数。 // 2. 头插迭代器(deque、list、forward_list) deque<int> d = { 10, 20, 30 }; // 使用 front_inserter 获得某个容器的头部插入迭代器 front_insert_iterator<deque<int>> it2 = front_inserter(d); // 对该迭代器的赋值操作,将会导致元素添加到容器的头部 it2 = 666; *it2 = 888; cout << d << endl; // 3. 指定位置插入的迭代器 // 使用 inserter 函数获得该迭代器 vector<int> v2 = { 10, 20, 30 }; insert_iterator<vector<int>> it3 = inserter(v2, v2.begin() + 1); it3 = 111; *it3 = 222; cout << v2 << endl; }
3.2 反向迭代器
reverse_iterator 适配器主要用于获得容器的反向迭代器。
void test04() { vector<int> v = { 10, 20, 30 }; // reverse_iterator<容器迭代器类型> // 指定位置:v.end 对于反向迭代器而言就是 30, 对于正向迭代器 30 后面的位置 reverse_iterator<vector<int>::iterator> it(v.end()); cout << *it << endl; cout << *(++it) << endl; cout << *(++it) << endl; }
3.3 流式迭代器
输出流迭代器:
void test05() { // 1. 输出流迭代器的使用 ostream_iterator<int> it1(cout, "|"); // 对 it1 这个输出流对象的赋值操作,都会导致将其输出到屏幕 it1 = 100; *it1 = 200; // 2. 使用输出流迭代器将容器元素打印到屏幕上 vector<int> v = { 10, 20, 30, 40, 50 }; // copy(开始,结束,目标开始); 将前两个参数标定的区间赋值到第三个参数指定的容器中 ostream_iterator<int> it2(cout, "|"); copy(v.begin(), v.end(), it2); /* for(; first != last; ++first) { *dst = *first; } */ }
输入流迭代器:
void test06() { // 1. 输出入流迭代器使用 // 输入需要标定开始输入、结束输入,所以需要创建两个对象 // istream_iterator<int> first(cin); // 将 cin 对象转换为迭代器对象 // istream_iterator<int> last; // 输入流结束迭代器对象 // *first 表示要从迭代器获取数据,如果没有数据会等待数据。 // 指向键盘输入的第一个数据 //int v1 = *first; //cout << v1 << endl; // 表示获取下一个输入 //int v2 = *(++first); //cout << v2 << endl; // 2. 通过输入流迭代器给容器赋值 // 结束输入:ctrl + z vector<int> v2; v2.resize(10); // 将大小变成10,并初始化10个对象 istream_iterator<int> my_first(cin); istream_iterator<int> my_end; // copy 内部是赋值操作,目前 v2 中不存在元素,也没有空间,此时是不能赋值。 copy(my_first, my_end, v2.begin()); cout << v2 << endl; }