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


    欢迎各位大佬光临本文章!!!

     

    还请各位大佬提出宝贵的意见,如发现文章错误请联系冰冰,冰冰一定会虚心接受,及时改正。

    本系列文章为冰冰学习编程的学习笔记,如果对您也有帮助,还请各位大佬、帅哥、美女点点支持,您的每一分关心都是我坚持的动力。

    我的博客地址:bingbing~bang的博客_CSDN博客https://blog.csdn.net/bingbing_bang?type=blog

    我的gitee:冰冰棒 (bingbingsupercool) - Gitee.comhttps://gitee.com/bingbingsurercool


    系列文章推荐

    冰冰学习笔记:《vector的简单模拟》

    冰冰学习笔记:《list的简单模拟》


    目录

    系列文章推荐

    前言

    1.反向迭代器的使用介绍

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


    前言

            反向迭代器是C++中容器内常见的一种迭代器模式,它与正常的迭代器截然相反,rbegin()指向的是容器末尾位置,rend()指向的则是容器开始位置,并且rbegin的++操作并不是向后移动,而是向前移动,逐步靠近rend()。因此,使用反向迭代器遍历得到的是逆置后的容器结果。

    1.反向迭代器的使用介绍

            反向迭代器并不是每个容器都具备,有些容器本身就不具备迭代器的操作,例如栈和队列,使用迭代器会改变其容器本身属性。有些容器则只支持正向迭代器,不支持反向迭代器,例如。最典型的例子就是单链表,因为单链表只有一个next指针,不具备指向前面元素的指针,更不可能具备反向迭代器。

            反向迭代器的使用与正向迭代器没有什么区别,就是反着来访问容器内容。

            拿链表来举例,按照我们常规的理解,rbegin指向的应该是链表最后一个位置的元素,这样解引用才能拿到最后一个数据,rend指向的则是原来end指向的位置,也就是头节点。可真的是这样吗?

            迭代器是具备类型分类的,迭代器分为单向迭代器,双向迭代器,随机迭代器。迭代器的分类可以帮助我们在使用算法函数时能够正确的传递参数。

     

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

            对于反向迭代器的实现,我们最先想到的就是重新封装一个类,然后重载里面的++,--操作符,使其向相反的位置移动。但是C++的大佬们并没有使用如此庸俗的手法。

            C++的大佬在实现的时候想的是尽可能多的复用,vector需要实现反向迭代器,list也需要实现反向迭代器,那我们能不能实现通用的一种方式,代码放在vector中能正常使用,放在list,deque中也能使用呢?

            因此,基于这种方式,大佬们将反向迭代器实现成了一种适配器模式,使用原先容器的正向迭代器来实现反向迭代器。

            每个反向迭代器使用原有容器的正向迭代器构建 ,并将运算符进行重载,返回对应的反向迭代器。最值得关注的是解引用操作符的重载,并不是将指向元素的迭代器直接进行访问操作,而是访问前一个位置的元素!

             这是什么原因呢?原因在于,大佬实现的反向迭代器并不是按照我们想的那样rbegin指向的最后一个位置,rend指向的头节点,而是rbegin就是使用end构建,二者指向同一个位置,rend使用begin构建,二者指向同一个位置。这样我们在进行解引用的时候就需要向前移动然后在访问,才能得到正确位置的元素。

            剩下的实现就是运算符的重载,对++,--进行封装。反向迭代器的++操作需要向前移动,因此我们内部将正向迭代器向前移动,然后返回。--操作则同理进行正向迭代器的++操作。

    1. namespace lb
    2. {
    3. template<class Iterator,class Ref,class Ptr>
    4. struct __reverse__iterator
    5. {
    6. Iterator _cur;//反向迭代器用正向迭代器构建
    7. typedef __reverse__iterator RIterator;
    8. __reverse__iterator(Iterator it)//构造
    9. :_cur(it)
    10. {}
    11. RIterator operator++()
    12. {
    13. --_cur;
    14. return *this;
    15. }
    16. RIterator operator++(int)
    17. {
    18. auto tmp = _cur;
    19. --_cur;
    20. return tmp;
    21. }
    22. RIterator operator--()
    23. {
    24. ++_cur;
    25. return *this;
    26. }
    27. RIterator operator--(int)
    28. {
    29. auto tmp = _cur;
    30. ++_cur;
    31. return tmp;
    32. //return _cur++;
    33. }
    34. Ref operator*()
    35. {
    36. auto tmp = _cur;
    37. return *(--tmp);
    38. }
    39. Ptr operator->()
    40. {
    41. return &(operator*());
    42. }
    43. bool operator !=(const RIterator& it)
    44. {
    45. return _cur != it._cur;
    46. }
    47. bool operator ==(const RIterator& it)
    48. {
    49. return _cur == it._cur;
    50. }
    51. };
    52. }

            对于list内部,我们就可以直接使用begin,end进行反向迭代器的构建。

    1. typedef __reverse__iterator reverse_iterator;
    2. typedef __reverse__iteratorconst T&, const T*> const_reverse_iterator;
    3. reverse_iterator rbegin()
    4. {
    5. return reverse_iterator(end());
    6. }
    7. reverse_iterator rend()
    8. {
    9. return reverse_iterator(begin());
    10. }
    11. const_reverse_iterator crbegin()const
    12. {
    13. return const_reverse_iterator(cend());
    14. }
    15. const_reverse_iterator crend()const
    16. {
    17. return const_reverse_iterator(cbegin());
    18. }

            这样我们实现的反向迭代器无论是deque还是list,vector都可以直接使用对应的正向迭代器进行构建。

  • 相关阅读:
    yml文件中&、<<、 * 是什么意思
    什么是上拉,下拉?
    MATLAB switch语句
    x265参数-early-skip
    【ARC133E】Cyclic Medians(数学)
    蒙特卡洛方法的简单应用
    Python之socket编程
    C. Even Number Addicts
    Python学习笔记
    mysql数据库通过binlog恢复数据
  • 原文地址:https://blog.csdn.net/bingbing_bang/article/details/127089618