STL与泛型编程<十>:迭代器适配器(Iterator Adapters)之逆向迭代器

此类迭代器可以使得算法能够以逆向(reverse mode)模式,安插模式(insert mode)进行工作,也可以流(streams)的模式搭配工作

逆向迭代器

声明

template <class Iterator> class reverse_iterator;

reverse迭代器是一种适配器,重新定义递增运算和递减运算,使其行为正好倒置,所有标准容器都允许使用reverse迭代器来遍历元素,例子

#include <iostream>
#include <list> 
#include <iterator> 
#include <algorithm>
#include <vector> 
using namespace std;

void print(int elem)
{
    cout << elem << ' ';
}

int main(void)
{
    list<int> col;
    for (int i=1; i<=9; ++i)
        col.push_back(i);
    for_each(col.begin(),col.end(),print);
    cout << endl;

    for_each(col.rbegin(),col.rend(),print);
    cout << endl;
    return 0;
} 

而for_each()代码如下

namespace std
{
    template <typename Iterator, class Operation>
    Operation for_each (Iterator act, Iterator end, Operation op)
    {
        while (act != end)
            op(*act);
            ++act;
    }
    return op;
}

容器的成员函数rbegin()和rend()各自返回一个逆向迭代器。也就是说rbegin()返回容器的尾部,而rend()返回容器的头部的前一个,因此就能解释为什么会出现逆向行为了。
通过如下代码更能清楚解释

rbegin() = container::reverse_iterator(end());
rend() = container::reverse_iterator(begin());
而逆向迭代器的++操作是会向反方向进行的

迭代器和逆向迭代器

可以将一般迭代器转化为一个reverse迭代器,当然原来的迭代器必须具有双向移动能力,注意转换前后迭代器的逻辑位置发生了变化
先看一例子

#include <iostream>
#include <list> 
#include <iterator> 
#include <algorithm>
#include <vector> 
using namespace std;

void print(int elem)
{
    cout << elem << ' ';
}

int main(void)
{
    vector<int> col;
    for (int i=1; i<=9; ++i)
        col.push_back(i);
    vector<int>::iterator pos;
    pos = find(col.begin(),col.end(),5);

    cout << "pos=" << *pos << endl;

    vector<int>::reverse_iterator rpos(pos);
    cout << "rpos=" << *rpos << endl;

    return 0;
}
/*
程序输出
pos=5
rpos=4
*/

为什么会这样?迭代器转换为逆向迭代器的时候发生了什么?
答:当迭代器转换为逆向迭代器的时候,它们指向同一个实际地点,但它们所代表的意义却不同了。
注意这是特性,主要由半开原则造成的,具体解释见下图即可
这里写图片描述
这里写图片描述
如果你有个区间,由两个迭代器定义出来,那么操作就会很简单,所有元素任然有效,你就会看出STL这样设计的优点。见下例子1

#include <iostream>
#include <deque> 
#include <iterator> 
#include <algorithm>

using namespace std;

int main(void)
{
    deque<int> col;
    for (int i=1; i<=9; ++i)
        col.push_back(i);

    deque<int>::iterator pos1,pos2;
    pos1 = find(col.begin(),col.end(),2);
    pos2 = find(col.begin(),col.end(),7);

    copy(pos1,pos2,ostream_iterator<int>(cout," ")); // 2 3 4 5 6 
    cout << endl;

    deque<int>::reverse_iterator rpos1(pos1);
    deque<int>::reverse_iterator rpos2(pos2);

    //copy(rpos1,rpos2,ostream_iterator<int>(cout," ")); //没打印,为什么
    copy(rpos2,rpos1,ostream_iterator<int>(cout," ")); // 6 5 4 3 2
    cout << endl;

    return 0;
} 

见下例子2

#include <iostream>
#include <deque> 
#include <iterator> 
#include <algorithm>

using namespace std;
void print(int elem)
{
    cout << elem << ' ';    
}

int main(void)
{
    deque<int> col;
    for (int i=1; i<=9; ++i)
        col.push_back(i);

    deque<int>::iterator pos1,pos2;
    pos1 = find(col.begin(),col.end(),2);
    pos2 = find(col.begin(),col.end(),7);
    for_each(pos1,pos2,print);   // 2 3 4 5 6 
    cout << endl;

    deque<int>::reverse_iterator rpos1(pos1);
    deque<int>::reverse_iterator rpos2(pos2);
//  for_each(rpos1,rpos2,print); //错误 
    for_each(rpos2,rpos1,print);   // 6 5 4 3 2  
    cout << endl;

    return 0;
} 
/*
刚开始写错了:
其实看看for_each()的源代码(源代码见上)就可以知道原因了:
rpos2在rpos1,因此会产生上面的错误 
*/

base()将逆向迭代器转会正常迭代器

base()是reverse_iterator型别的一个成员函数,
见下面例子

#include <iostream>
#include <deque> 
#include <iterator> 
#include <algorithm>

using namespace std;

int main(void)
{
    deque<int> col;
    for (int i=1; i<=9; ++i)
        col.push_back(i);

    deque<int>::iterator pos;
    pos = find(col.begin(),col.end(),3);
    cout << "*pos = " << *pos << endl; // 3

    deque<int>::reverse_iterator rpos(pos);
    cout << "*rpos = " << *rpos << endl; // 2

    //deque<int>::reverse_iterator rpos(pos);这样写错误 
    deque<int>::iterator rrpos;
    rrpos = rpos.base();
    cout << "*rrpos = " << *rrpos << endl; // 3

    return 0;
}

总结

逆向迭代器的相关声明继使用方法如下

container::iterator pos;
...
container::reverse_iterator rpos(pos);
...
pos = rpos.base();

注意使用STL算法时,若区间由逆向迭代器组成,一定多注意区间的有效性

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值