文章目录

  • 1.迭代器的分类
  • 2.反向迭代器的使用
  • 3.反向迭代器的模拟实现
  • 4.list类的反向迭代器实现

1.迭代器的分类

我们随便打开一个容器,看迭代器相关的接口,都可以发现,支持迭代器的容器,其迭代器有以下几类

  • 正向迭代器
  • const正向迭代器
  • 反向迭代器
  • const反向迭代器

2.反向迭代器的使用

对于正向迭代器,我么已经很熟悉了,在之前的STL容器的模拟实现中都已经实现过了。那么现在来看看反向迭代器

❗❗反向迭代器的特点

✅反向迭代器的迭代顺序与正向迭代器相反

✅rbegin()相当于end()

✅rend()相当于begin()

✅反向迭代器++相当于正向迭代器–

那么现在,让我们来看一看反向迭代器的使用与正向迭代器的区别

void Test1()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);v.push_back(6);auto rit = v.rbegin();while (rit != v.rend()){cout << *rit << " ";++rit;}cout << endl;
}

可以看到,反向迭代器的使用和正向迭代器没有任何区别,只是迭代的顺序不同。

3.反向迭代器的模拟实现

对于反向迭代器的实现,我们去参考一下库里面是怎么实现的

注:这里参照的库是SGI的3.0版本,与侯捷老师的STL源码剖析相对应

这里以list的反向迭代器实现为例,可以看到库里面对反向迭代器的实现是通过实例化reverse_iterator类来实现的,通过用法可以推测出来reverse_iterator类模板的实现逻辑是通过传入的正向迭代器的类型来实例化出不同类的反向迭代器,这里反向迭代器就可以理解成一个容器适配器

下面来看一下reverse_iterator类的实现,这个类在头文件stl_iterator中

通过观察库里面的代码,对模拟实现反向迭代器已经大概有了了解,但是其中出现了新语法:萃取,笔者正在学习的路上,目前的能力对萃取的理解有难度,所以本次模拟实现就不使用萃取的方式,而是使用和list迭代器同样的解决方案——传模板参数的方式解决【C++】list的模拟实现

所以,我们可以得到反向迭代器类的框架如下

template<class Iterator, class Ref, class Ptr>//这里对参数的设计参考之前list迭代器的这几
class reverse_iterator
{typedef reserve_iterator<Iterator, Ref, Ptr> Self;//这里类型实例化出来太长了,做一个重命名
public://......
private:Iterator _it;
};

成员函数的实现

参照list迭代器类的成员函数,我们需要设计的成员函数有:

  • 解引用
  • 前置后置的++–
  • ->运算符
  • != 和==

按照我们的理解,很轻松能够写出来以下的成员函数。

reverse_iterator(Iterator it)//构造函数:_it(it){}
Self& operator++()//前置++
{--_it;return *this;
}
Self operator++(int)//后置++
{Self tmp = _it;--_it;return tmp;
}
Self& operator--()//前置--
{++_it;return *this;
}
Self operator--(int)//后置--
{Self tmp = _it;++_it;return tmp;
}
Ref operator*()
{return *this;
}
Ptr operator->()
{return &(operator*());
}
bool operator!=(const Self& s) const
{return _it != s._it;
}
bool operator==(const Self& s) const
{return _it == s._it;
}

接下来和库里面的对比以下吧

诶?这和我们实现的不一样啊,为啥嘞?“源码之下了无秘密”,我们去看一下list中对迭代器接口的实现

哦哦懂了,原来是这样,在list中对rbegin的实现是使用end()构造的,end返回的是最后一个元素的下一个位置

如果我们要拿到最后一个元素,会调用rbegin()接口,此时如果要拿到最后一个元素,当然要让rbegin先–,指向最后一个元素之后再解引用。

所以最终对于*得到了以下实现,其余不用改变

当然,如果你愿意更改所有容器对反向迭代器的传参,也可以按照上文中的实现方式实现。

Ref operator*()
{Iterator tmp = _it;return *(--tmp);
}

最后,我们对返现迭代器类的实现完整代码如下

namespace zht
{template<class Iterator, class Ref, class Ptr>//这里对参数的设计参考之前list迭代器的这几class reverse_iterator{typedef reserve_iterator<Iterator, Ref, Ptr> Self;//这里类型实例化出来太长了,做一个重命名public:reverse_iterator(Iterator it)//构造函数:_it(it){}Self& operator++()//前置++{--_it;return *this;}Self operator++(int)//后置++{Self tmp = _it;--_it;return tmp;}Self& operator--()//前置--{++_it;return *this;}Self operator--(int)//后置--{Self tmp = _it;++_it;return tmp;}Ref operator*(){Iterator tmp = _it;return *(--tmp);}Ptr operator->(){return &(operator*());}bool operator!=(const Self& s) const{return _it != s._it;}bool operator==(const Self& s) const{return _it == s._it;}private:Iterator _it;};
}

4.list类的反向迭代器实现

有了上述迭代器类的实现,我们现在可以顺便把之前模拟实现的list类中的反向迭代器加上了

typedef zht::reverse_iterator<iterator, T&, T*> reverse_iterator;//反向迭代器
typedef zht::reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;//const反向迭代器
reverse_iterator rbegin()
{return reverse_iterator(end());
}
reverse_iterator rend()
{return reverse_iterator(begin());
}
const_reverse_iterator rbegin() const
{return const_reverse_iterator(end());
}
const_reverse_iterator rend() const
{return const_reverse_iterator(begin());
}

至此,就把STL的迭代器完整实现了。

【C++】反向迭代器的实现相关推荐

  1. Vector反向迭代器使用

    反向迭代器 1 反向迭代器其实没什么特殊的,他只是在遍历的方向上和普通迭代器不通而已:每一个容器里面都有Iterator(迭代器),可以从容器的begin位置到end-1位置,通过++来遍历.同样也有 ...

  2. boost::stl_interfaces模块实现反向迭代器的测试程序

    boost::stl_interfaces模块实现反向迭代器的测试程序 实现功能 C++实现代码 实现功能 boost::stl_interfaces模块实现反向迭代器的测试程序 C++实现代码 #i ...

  3. 迭代器和反向迭代器,常量迭代器和非常量迭代器

    迭代器的类型共有4种:<T>::Iiterator,<T>::const_iterator,<T>::reverse_iterator,<T>::con ...

  4. 洛谷3320 SDOI2015寻宝游戏(set+dfs序)(反向迭代器的注意事项!)

    被\(STL\)坑害了一个晚上,真的菜的没救了啊. 准确的说是一个叫\(reverse\ iterator\)的东西,就是我们经常用的\(rbegin()\) 有一个非常重要的性质 在反向迭代器中,+ ...

  5. c++STL的反向迭代器

    反向迭代器 反向迭代器是一种反向遍历容器的迭代器.也就是,从最后一个元素到第一个元素遍历容器.反向迭代器将自增(和自减)的含义反过来了:对于反向迭代 器,++ 运算将访问前一个元素,而 – 运算则访问 ...

  6. 插入迭代器、流迭代器、反向迭代器、移动迭代器

    文章目录 前言 插入迭代器 inserter front_inserter back_inserter iostream迭代器 istream_iterator 读取输入流 istream_itera ...

  7. std::string中的反向迭代器rbegin()和rend()

    在std::string中,有个接口是rbegin()和rend(),分别表示string字符串的倒数第一个字符和正数第一个字符: rbegin():表示string字符串的倒数第一个字符 rend( ...

  8. python反向迭代器_Python中对象迭代与反迭代的技巧总结

    一.如何实现可迭代对象和迭代器对象? 实际案例 某软件要求从网络抓取各个城市气味信息,并其次显示: 北京: 15 ~ 20 天津: 17 ~ 22 长春: 12 ~ 18 ...... 如果一次抓取所 ...

  9. Leetcode 58 之反向迭代器的使用

    题目: Given a string s consists of upper/lower-case alphabets and empty space characters' ', return th ...

  10. 【C++】迭代器、反向迭代器详解

    参考: http://c.biancheng.net/view/338.html https://blog.csdn.net/kjing/article/details/6936325 https:/ ...

最新文章

  1. p沟道mos管导通条件_10天电子入门-MOS管
  2. 两个免费转换视频的软件,实现服务器端Video2FLV
  3. hdu 5563 Clarke and five-pointed star (枚举)
  4. 别让扁平化设计平淡无奇
  5. 记录qt窗口在拖动过程中出现的问题
  6. 《算法之道》精华 难解问题部分
  7. MFC开发IM-第十八篇、如何设置编辑框的内容
  8. PyQT5-QProgressBar
  9. [bug解决] cannot import name ‘_validate_lengths‘ from ‘numpy.lib.arraypad‘
  10. 关于深入浅出MFC(1)
  11. 30款免费3D建模软件,总有一款适合你!
  12. 推荐 5 款良心网盘,免费、空间大、不限速!
  13. 【颗粒归仓】(一)jQuery easyui datagrid 的数据加载
  14. 小米air12.5做Java_到底够不够用? 小米笔记本Air12.5性能测试
  15. c语言编译器中输出虚线,请教:c语言中用什么命令画虚线
  16. JavaScript中的onload详解
  17. 局域网 git服务器 虚拟机,centos71虚拟机搭建git服务器
  18. 生产用料清单-在制材料数量
  19. 前端三件套之JS速成
  20. 图像基本处理——图像阈值和平滑

热门文章

  1. 白嫖党的福音,这5款实用的黑科技软件,干货满满,真是相见恨晚
  2. 高频电子线路——第三章高频小信号放大器
  3. 知乎引流回答问题需要注意什么?详细的方案一路指引
  4. python视频格式转换_将ppt文件转成mp4视频的Python脚本
  5. 零序电流、零序电压与脱扣器
  6. 【第113期】聊聊网易某工作室的策划笔试题
  7. webupload 上传插件 完美版 - 拿走直接用
  8. linux各个文件夹作用是什么,我的世界游戏文件夹目录作用介绍 各个文件夹都是什么用...
  9. matlab的svpwm逆变器,基于svpwm三相逆变器在matlab下的仿真研究.doc
  10. 企业认证ISO27001的必要性