浅谈C++反向迭代器的设计

 更新时间:2023年04月27日 11:12:33   作者:看到我请叫我滚去学习Orz  
本文主要介绍了浅谈C++反向迭代器的设计,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

STL中不少的容器需要有迭代器这样的设计,特别是正向迭代器,几乎每个容器都有自己的特定实现方式,有了正向迭代器之后,我们还要提供反向迭代器以供一些特殊的需求,但是许多容器的正向迭代器实现的方式不一样,如果我们要实现其反向迭代器,每个容器的反向迭代器的实现方式也不一样,有没有一种方法能够统一反向迭代器的实现方式呢?

有的,那就是拿已有的正向迭代器进行封装,这样只要我们实现了正向迭代器,反向迭代器自然而然就形成了,本篇文章我们就来一起探究这种设计方式。

一、反向迭代器的结构

我们设计的反向迭代器是用正向迭代器实现的,这样反向迭代器的实现方式就统一了,那么我们反向迭代器的成员变量就是一个正向迭代器,关于成员函数,我们反向迭代器提供的接口与正向迭代器提供的接口一样。

//第一个模板参数传递 正向迭代器,第二个传递 迭代器的引用 第三个传递 迭代器的地址
 template<class Iterator, class Ref, class Ptr>
 //用struct定义类,因为我们想要公开我们的接口
 struct _reverse_iterator
 {
     //对自己进行typedef方便使用
     typedef _reverse_iterator<Iterator, Ref, Ptr> self;
    //成员变量 是一个正向迭代器
    Iterator _current;
    //构造函数   用一个正向迭代器进行初始化反向迭代器对象
    _reverse_iterator(Iterator it)
        :_current(it)
    {}
    //*运算符重载
    Ref operator*();
    //前置++运算符重载
    self& operator++();
    //后置++运算符重载
    self operator++(int)
    //前置--运算符重载
    self& operator--()
    //后置--运算符
    self operator--(int)
    //->操作符
    Ptr operator->()
    //关系运算符
    bool operator!=(const self& s);
    bool operator==(const self& s);
 }

容器类内的rbegin与rend 函数

//类内使用反向迭代器
class myclass
{
     //此类内要配套有一个正向迭代器iterator,然后传给外面的反向迭代器
     //将反向迭代器进行typedef方便使用
     typedef _reverse_iterator<iterator, T&, T*> reverse_iterator;
      //反向迭代器
     typedef _reverse_iterator<iterator, const T&, const T*> const_reverse_iterator;
     //反向迭代器
     reverse_iterator rbegin()
     {
        return reverse_iterator(end());
     }
     reverse_iterator rend()
     {
         return reverse_iterator(begin());
     }
     //const反向迭代器
     const_reverse_iterator rbegin() const
     {
         return const_reverse_iterator(end());
     }
     const_reverse_iterator rend() const
     {
        return const_reverse_iterator(begin());
     }
};

注意: 反向迭代器这里我们采用了对称结构便于理解对比,但这也导致我们后面在进行*解引用操作符时要解引用前一个位置!

二、反向迭代器的接口实现

1、*运算符重载

我们可以创建一个局部对象,对局部对象进行--找到前一个位置,然后再进行解引用返回就行了。

//*运算符重载
Ref operator*()
{
    //这里是不用写拷贝构造的,默认的拷贝构造会对内置类型进行值拷贝,对自定义类型调用它的拷贝构造
    Iterator tmp = _current;
    --tmp;
    return *tmp;
}

2、算术运算符 ++ - -的重载

由于我们的反向迭代器是由正向迭代器实现的,反向迭代器++就相当于正向迭代器- - ,明白了这个就很好实现算术运算符重载了。

//前置++运算符重载
self& operator++()
{
    --_current;
    return(*this);
}
//后置++运算符重载
self operator++(int)
{
    //保存当前对象
    self tmp(*this);
    --_current;
    //返回--之前的对象
    return tmp;
}
//前置--运算符重载
self& operator--()
{
    ++_current;
    return (*this);
}
//后置--运算符
self operator--(int)
{
    self tmp(*this);
    ++_current;
    return tmp;
}

3、->操作符重载

->运算符重载我们只需要返回容器中存储的自定义类型的对象的地址就行了,我们可以先调用operator*()拿到容器中存储的对象,然后再进行取地址&

Ptr operator->()
{
    return &(operator*());
}

4、关系运算符

要判断两个反向迭代器相不相等,只需要判断反向迭代器里面的成员变量相不相等就行了。

//关系运算符
bool operator!=(const self& s)
{
    return _current != s._current;
}
bool operator==(const self& s)
{
    return _current == s._current;
}

到这里我们的反向迭代器就已经形成了。

三、关于反向迭代器的一些讨论

由于我们的反向迭代器是用模板写的,当我们将vector的迭代器类型传递过去时,我们的反向迭代器就变成了vector的反向迭代器,当我们将list的迭代器传递过去时,就形成了list的反向迭代器。

传递的迭代器必须的二元迭代器,可以++ ,- -。forward_list的迭代器就不行!

例如:实现vector的反向迭代器,我们只需要在类内部传递一下正向迭代器,然后typedef一下就行了。

template<class T>
class vector
{
public:
    //正向迭代器
    typedef  T* iterator;
    //反向迭代器   将正向迭代器进行传递给反向迭代器
    typedef _reverse_iterator<iterator, T&, T*> reverse_iterator;
    typedef _reverse_iterator<iterator, const T&, const T*> const_reverse_iterator;
    //普通迭代器  ------------------------------------------------
    iterator begin();
    iterator end();
    //const迭代器
    typedef const T* const_iterator;
    const_iterator begin() const;
    const_iterator end() const;
    //反向迭代器
    reverse_iterator rbegin()
    {
        return reverse_iterator(end());
    }
    reverse_iterator rend()
    {
        return reverse_iterator(begin());
    }
    //const反向迭代器
    const_reverse_iterator rbegin() const
    {
        return const_reverse_iterator(end());
    }
    const_reverse_iterator rend() const
    {
        return const_reverse_iterator(begin());
    }
    ...... 
    ...... 
    ...... 
};

到此这篇关于浅谈C++反向迭代器的设计的文章就介绍到这了,更多相关C++反向迭代器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++非递归遍历磁盘文件和递归遍历磁盘文件的程序示例

    C++非递归遍历磁盘文件和递归遍历磁盘文件的程序示例

    这篇文章主要介绍了C++非递归遍历磁盘文件和递归遍历磁盘文件的程序示例,大家可以参考使用二种方法
    2013-11-11
  • C语言数据结构之堆排序详解

    C语言数据结构之堆排序详解

    堆是计算机科学中一类特殊的数据结构的统称,通常是一个可以被看做一棵完全二叉树的数组对象。而堆排序是利用堆这种数据结构所设计的一种排序算法。本文将通过图片详细介绍堆排序,需要的可以参考一下
    2022-03-03
  • C/C++内存管理详情

    C/C++内存管理详情

    这篇文章主要通过描述了C/C++内存分布、C/C++的一些函数理方面来展开C/C++内存管理的内容,需要的朋友请参考下文
    2021-08-08
  • C语言顺序表实现代码排错

    C语言顺序表实现代码排错

    这篇文章主要介绍了C语言顺序表实现方法,大家参考使用吧
    2013-12-12
  • 用C语言实现从文本文件中读取数据后进行排序的功能

    用C语言实现从文本文件中读取数据后进行排序的功能

    这是一个十分可靠的程序,这个程序的查错能力非常强悍。程序包含了文件操作,归并排序和字符串输入等多种技术。对大家学习C语言很有帮助,有需要的一起来看看。
    2016-08-08
  • C++实现LeetCode(309.买股票的最佳时间含冷冻期)

    C++实现LeetCode(309.买股票的最佳时间含冷冻期)

    这篇文章主要介绍了C++实现LeetCode(309.买股票的最佳时间含冷冻期),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • C语言安全编码之数值中的sizeof操作符

    C语言安全编码之数值中的sizeof操作符

    这篇文章主要介绍了C语言安全编码的数值中的sizeof操作符用法注意事项,需要的朋友可以参考下
    2014-07-07
  • C++智能指针shared_ptr与weak_ptr的实现分析

    C++智能指针shared_ptr与weak_ptr的实现分析

    shared_ptr是一个标准的共享所有权的智能指针,允许多个指针指向同一个对象,定义在 memory 文件中,命名空间为 std,这篇文章主要介绍了C++ 中 shared_ptr weak_ptr,需要的朋友可以参考下
    2022-09-09
  • C语言 单向链表的增删查改快速掌握

    C语言 单向链表的增删查改快速掌握

    单向链表特点是链表的链接方向是单向的,访问要通过顺序读取从头部开始。链表是使用指针构造的列表,是由一个个结点组装起来的,又称为结点列表。其中每个结点都有指针成员变量指向列表中的下一个结点,head指针指向第一个结点称为表头,而终止于最后一个指向nuLL的指针
    2021-11-11
  • C++数据结构之list详解

    C++数据结构之list详解

    list是一种序列式容器。list容器完成的功能实际上和数据结构中的双向链表是极其相似的,list中的数据元素是通过链表指针串连成逻辑意义上的线性表,也就是list也具有链表的主要优点,即:在链表的任一位置进行元素的插入、删除操作都是快速的
    2021-11-11

最新评论