1. 迭代器适配器
1.1 reverse_iterator 反向迭代器适配器
这个迭代器适配的作用是将迭代器逆转.
如rbegin()
和rend()
就是调用这个适配器, 如下图:
本来begin()
迭代器++之后是往右边走的, 然后*
运算符取的是迭代器右边的元素;
当使用rbegin()
之后, rbegin()
指向的地方和end()
一样, ++是从右往左走, *
运算符取的是迭代器左边的元素.
怎么会这么神奇呢? 这到底是怎么做到的呢?
具体实现下图右边代码告诉了我们结果.
分析:
- 当我们调用
rbegin()
时, 函数里面调用的是reverse_iterator(end())
, 然后进入此类的构造函数 - 构造函数保存当前迭代器
- 当我们调用
++
时候, 类就会调用operator++
操作符重载, 里面调用的是相反的操作:--
- 当我们调用
*
的时候, 类调用operator*
, 里面做的操作是, 先--
, 再取值*
.
剩下各种操作都是类似手法.
1.2 inserter
这个inserter适配器的作用就是里面重载了=
运算符, 分析同上:
2. X适配器
2.1 ostream_iterator
看如下代码, 可以用copy算法把容器里面的元素打印到终端.
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <set>
#include <iterator> //ostream_iterator
using namespace std;
void test01(){
vector<int> my_vector;
for(int i = 1; i < 10; ++i){
my_vector.push_back(i*10);
}
ostream_iterator<int> out_it(cout, ",");
copy(my_vector.begin(), my_vector.end(), out_it);
}
int main(int argc, char *argv[]){
test01();
return 0;
}
输出:
10,20,30,40,50,60,70,80,90,
以上操作是如何实现的呢?
看下图:
- 当我们调用copy的时候, 要注意copy里面执行的是
=
操作, 因此我们从这里下手,ostream_iterator
就是这样做的 ostream_iterator
创建一个类, 类里面保存了cout
和分隔符,
, 等copy调用=
时候, 便调用=
重载, 在里面把value
输出到cout
去.
2.2 istream_iterator
看如下代码:
void test01(){
double value1, value2;
cout << "please, insert two values: " << endl;
istream_iterator<double> eos;
istream_iterator<double> iit(cin);
if(iit != eos){
value1 = *iit;
}
++iit;
if(iit != eos){
value2 = *iit;
}
cout << "value1: " << value1 << ", " << "value2 : " << value2 << endl;
}
上诉代码可以从终端接受2个输入, 放在value1和value2中. 这是怎么做到的呢?
那我们就要看一下istream_iterator
类的代码了, 如下图右侧:
- 首先定义
eos
, 调用构造函数, 把0
赋给in_stream
- 接着定义
iit
, 调用构造函数, 把cin
赋给in_stream
, 注意是引用, 然后构造函数里面做的事情是++*this
. 因为++
被重载过了,iit
对象想调用++的话, 先用*this
取对象, 然后调用++. - 调用的过程是这样的: 进入++, 先判断
in_stream
是否为空, 因为cin不是空, cin是阻塞操作, 等待输入 - 然后等我们输入数字, 比如我们输入
20 32
, 这时候cin先从缓冲区读入20(因为cin内部处理不读入空格), 然后in_stream
里面就有内容了(因为是引用), 之前在阻塞的函数就*in_stream>>value
了, 然后iit的对象就创建成功了. 要注意的是,*in_stream>>value
插入成功了, 返回的是true, 取反后是0, 所以不会执行in_steam=0
- 等我们执行
value1 = *iit
时候, 直接返回value
- 然后执行
++iit
, 继续进入前置++重载运算符函数中去, 继续把新的值写入value - 下面执行就比较简单了.
另外一个例子:
用copy, istream_iterator 以及inserter实现把容器的内容输入到cin: