在上篇文章实现了 list 后,我们实现了其对应的迭代器,但是对于 list,还有一个反向迭代器我们呢没有实现,但是反向迭代器不仅仅可以在 list 中使用,在 vector 中我们进行适配,同样也可以使用,所以我们这篇博客我们实现的反向迭代器是实现迭代器适配器的作用的。

我们反向迭代器的思路是复用正向迭代器的功能,使用一个正向迭代器来创建一个反向迭代器,如果是vector的正向迭代器创建的就是vector的反向迭代器,如果是 list 的正向迭代器,那创建的就是 list 的反向迭代器。

目录

一、反向迭代器定义

二、反向迭代器的功能

2.1 operator++

2.2 operator--

2.3 operator*

2.4 operator->

2.5 operator!=

三、list+iterator+resever_iterator


一、反向迭代器定义

同样,我们之前实现普通迭代器是声明了一个迭代器类。此时,我们也要定义一个反向迭代器类。

而这个反向迭代器是由正向迭代器构造而来的。

template <class iterator,class Ref,class Ptr>class _resever_iterator_list{Iterator _cur;typedef __reverse_Iterator<Iterator,Ref,Ptr> RIterator;}//根据一个正向迭代器创建我们的反向迭代器__reverse_Iterator(Iterator it):_cur(it){}

在list类中,我们要重命名一下反向迭代器,并将其调用接口写好。

其中关于模板参数的书写,我们要注意一下。

第一个模板参数是普通迭代器类型。

第二个是迭代器其指向其数据的数据类型的引用。

第三个是迭代器其指向其数据的数据类型的指针。

并在此基础上定义好const_Riterator.

//正向迭代器
typedef __list_iterator<T, T&, T*>  iterator;
typedef __list_iterator<T, const T&, const T*> const_iterator;//反向迭代器
typedef __reverse_Iterator<iterator, T&, T*> reverse_iterator;
typedef __reverse_Iterator<const_iterator, const T&, const T*> const_reverse_iterator;

这样的好处是,调用普通的 rbegin() 则创建普通的反向迭代器,其中 operator* 的返回值是可修改的,operator-> 的返回值也是可修改的指针。

而 const 成员调用的是 const 型rbegin(),则创建了const_Riterator。

以下是 list 中通过普通迭代器构造出反向迭代器的 rbegin()、rend()。

//使用 end() 构造反向迭代器的 rbegin()
Riterator rbegin()
{return Riterator(end());
}
const_Riterator rbegin() const
{return const_Riterator(end());
}
Riterator rend()
{return Riterator(begin());
}
const_Riterator rend() const
{return const_Riterator(begin());
}

二、反向迭代器的功能

因为反向迭代器是使用正向迭代器构造的,所以反向迭代器的功能都是建立在正向迭代器一系列运算符重载已经实现的基础上完成的。

2.1 operator++

//反向迭代器的++ 相当于 正向迭代器的--
Riterator operator ++()
{_cur--;return *this;
}
Riterator operator ++(int)
{Riterator temp(_cur);_cur--;return temp;
}

2.2 operator--

Riterator operator --()
{_cur++;return *this;
}
Riterator operator--(int)
{Riterator temp(_cur);_cur++;return temp;
}

2.3 operator*

这里先明确一点 STL 中,反向迭代器的rbegin()是由 list 的 end() 构造的,也就是_head节点。所以我们在解引用的时候,其实是返回其前一个位置的数据。这样做的好处是为了做到迭代器指向的对称。

Ref operator*()
{//rebegin 是由 end 构造的,所以*是要返回_cur的上一个位置auto temp = _cur;--temp;return *temp;
}

2.4 operator->

Ptr operator->()
{//返回上一个位置的 解引用return &(operator*());
}

2.5 operator!=

//注意 要使用const 引用 因为存在 it 是临时变量的可能
bool operator!=(const Riterator& it)
{return _cur != it._cur;
}

三、list+iterator+resever_iterator

namespace Brant
{template <class T>class _list_node{public://因为prev指向的是节点,所以要使用_list_node<T>*_list_node<T>* _prev;_list_node<T>* _next;T _data;//创建节点时,进行初始化_list_node(const T& x = T()):_data(x),_next(nullptr),_prev(nullptr){}};//list的迭代器,就是一个模仿指针的类template <class T,class Ref,class Ptr>class __iterator_list{public:typedef _list_node<T> Node;typedef __iterator_list<T,Ref,Ptr> iterator;Node* _node;//要先传来一个list节点  ,才能创建一个迭代器__iterator_list(Node* node):_node(node){}T& operator*(){return _node->_data;}//注意,end() 传入的是临时变量,所以要使用const 传参bool operator!=(const iterator& it){return _node != it._node;}iterator& operator++(){_node = _node->_next;//node是list_node    *this才是迭代器return *this;}iterator operator++(int){//要先创建一个 迭代器iterator temp(_node);_node = _node->_next;return temp;}iterator operator--(){_node = _node->_prev;return *this;}iterator operator--(int){iterator temp(_node);_node = _node->_prev;return temp;}//往list中存放 自定义类型就很需要->操作符//如果data中存放的是自定义类型//即很容易访问到 自定义类型中的数据。T& operator->(){return &(operator*());}};//复用,迭代器适配器template <class iterator,class Ref,class Ptr>class _resever_iterator_list{public:iterator _cur;typedef _resever_iterator_list<iterator,Ref,Ptr> Riterator;//使用一个正向迭代器构造一个反向迭代器_resever_iterator_list(iterator it):_cur(it){}//反向迭代器的++ 相当于 正向迭代器的--Riterator operator ++(){_cur--;return *this;}Riterator operator ++(int){Riterator temp(_cur);_cur--;return temp;}Riterator operator --(){_cur++;return *this;}Riterator operator--(int){Riterator temp(_cur);_cur++;return temp;}Ref operator*(){//rebegin 是由 end 构造的,所以*是要返回_cur的上一个位置auto temp = _cur;--temp;return *temp;}Ptr operator->(){//两种都可以//return _cur.operator->();//return &(*_cur;);//返回上一个位置的 解引用return &(operator*());}/*    bool operator !=(const Riterator& it){return _cur!=it->_cur;}*/// .操作符是直接进行使用的 .操作符是无法重载的bool operator!=(const Riterator& it){return _cur != it._cur;}};template <class T>class list{public://注意 typedef ,第一个参数是正向迭代器,第二个 数据类型data的引用,第三个data的指针typedef _list_node<T> Node;typedef __iterator_list<T,T&,T*> iterator;typedef __iterator_list<T,const T&,const T*> const_iterator;typedef _resever_iterator_list<iterator, T&, T*> Riterator;typedef _resever_iterator_list<const_iterator, const T&, const T*> const_Riterator;//直接使用this指针进行构造void empty_Init(){_head= new Node;_head->_next = _head;_head->_prev = _head;}//实现一个无参的构造list(){empty_Init();}//一个带参的构造//template <class InputIterator>//list(InputIterator first, InputIterator last)//{//}拷贝构造  st2(st1);//list(const list<T>& lt)//{//   empty_Init();// std::swap()//}//插入数据void push_back(const T& x){//prev  tail  newnodeNode* newnode = new Node(x);Node* tail = _head->_prev;newnode->_next = _head;newnode->_prev = tail;tail->_next = newnode;_head->_prev = newnode;}iterator begin(){return iterator(_head->_next);}const_iterator begin() const{return const_iterator(_head->_next);}iterator end(){return iterator(_head);}const_iterator end() const{return const_iterator(_head);}Riterator rbegin(){return Riterator(end());}const_Riterator rbegin() const{return const_Riterator(end());}Riterator rend(){return Riterator(begin());}const_Riterator rend() const{return const_Riterator(begin());}private:Node* _head;};
}

【C++】STL中 list 反向迭代器的模拟实现相关推荐

  1. C++【STL】【反向迭代器】

    目录 一.反向迭代器的简介 1.什么是反向迭代器 2.方向迭代器的实现 二.反向迭代器的相关问题 1.为什么在operator*中需要--迭代器 2.适配list的反向迭代器 3.适配vector的反 ...

  2. 冰冰学习笔记:反向迭代器的模拟

    欢迎各位大佬光临本文章!!! 还请各位大佬提出宝贵的意见,如发现文章错误请联系冰冰,冰冰一定会虚心接受,及时改正. 本系列文章为冰冰学习编程的学习笔记,如果对您也有帮助,还请各位大佬.帅哥.美女点点支 ...

  3. 【C++】STL——反向迭代器的模拟实现:迭代器适配器

    文章目录 前言 1. list 的反向迭代器模拟实现 2. 思考 3. 库里面反向迭代器的实现--迭代器适配器 4. 反向迭代器模拟实现的改进--适配器模式 5. 适配器模式的实现--一劳永逸 6. ...

  4. 反向迭代器reverse_iterator模拟实现

    准备工作 相同的命名空间可以分割在不同的文件中,编译器最后都会合成在同一个命名空间下. 我们的reverse_iterator是个适配器,为什么叫适配器,是因为它需用正向迭代器做适配.简言之,反向迭代 ...

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

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

  6. STL中容器vector迭代器失效的相关问题

    迭代器失效,有两个层面的意思: 无法通过迭代器++,–操作遍历整个stl容器.记作: 第一层失效. 无法通过迭代器存取迭代器所指向的内存. 记作: 第二层失效. vector是个连续内存存储的容器,如 ...

  7. C++反向迭代器的原理+模拟实现+萃取

    反向迭代器实际上就是在正向迭代器的基础上将其转换一下就变成了反向的,里面会传一个迭代器模板,这个模板随便是谁的迭代器模板,可以是list的,vector的等等,其只要有一个模板,引用了正向迭代器,其他 ...

  8. 模拟实现list和vector反向迭代器

    学习这部分知识,需要你了解vector和list的正向迭代器知识以及容器适配器知识,可以阅读我写的另外三篇vector.list.容器适配器 知识的博客!其中list知识内容尤其重要且难度要求很高! ...

  9. C++ stack,queue(补充):deque,反向迭代器

    目录 1.deque​编辑 2.反向迭代器 1.deque vector和list的优缺点  效率比较 2.反向迭代器 和正向迭代器相比,除了++/--时方向相反,其他操作基本一致.下面为list的反 ...

最新文章

  1. Cause:compileSdkVersion is not specified
  2. exchange 2003配置ASSP 反垃圾邮件
  3. 监控子进程,退出就重启进程 ,简单版本
  4. 中国自主研制出的速度最高的巨型计算机是,2018年,中国自主研制出的速度最高的巨型计算机是。...
  5. $digest already in progress 解决办法——续
  6. 数学之路(2)-数据分析-R基础(2)
  7. Python 删除满足条件的某些行
  8. C++Windows下CONTAINING_RECORD宏的用法和详解
  9. 在线JSON转flow工具
  10. nginx开机启动脚本
  11. cp复制多个文件到指定目录
  12. 新加坡大数据初创公司 Latize 获 150 万美元风险融资
  13. 机器学习笔记(七):线性回归 | 凌云时刻
  14. 雕刻机c语言程序,基于51单片机的激光雕刻机
  15. ASP.NET Core中的TagHelper及其用法
  16. 向量相似度度量(二):EMD (Earth Mover's Distance)的MATLAB对照实现
  17. html图片自动适应屏幕代码,css让图片宽度自适应屏幕的例子
  18. 表格进阶03——简历制作(用表格布局)
  19. Linux基础知识与实操-篇三: 文件压缩打包与vim基本使用
  20. Mac上解决XXX.app已损坏 无法打开

热门文章

  1. Linux设置启动图标
  2. STM32 第7讲 STM32F407系列系统架构及映射
  3. Python简单CURD
  4. 电磁兼容(EMC)基础知识
  5. 分享:我的.Net武器库 ------ 新.Net架构必备工具列表
  6. 在迅捷CAD编辑器中怎么改文字字体
  7. deflate及gzip格式说明
  8. Web服务器处理HTTP压缩之gzip、deflate压缩
  9. 《学习opencv》笔记——矩阵和图像操作——cvMax,cvMaxS,cvMerge,cvMin and cvMinS
  10. Matlab 数组写入文件