• C++ 反向迭代器


    反向迭代器的++即正向迭代器的--,反向迭代器的--即正向迭代器的++,反向迭代器和正向迭代器的很多功能都是相似的,因此我们可以复用正向迭代器作为反向迭代器的底层容器来封装,从而实现出反向迭代器,即:反向迭代器内部可以包含一个正向迭代器,对正向迭代器的接口进行包装

    这样一来我们可以实现任意容器的反向迭代器,如果用的是vector的正向迭代器,那么就封装出vector的反向迭代器,如果用的是list的正向迭代器,那么就封装出list的反向迭代器,这就是迭代器适配器了

    反向迭代器:

    1. template<class Iterator,class Ref,class Ptr>
    2. class ReverseIterator
    3. {
    4. typedef ReverseIterator Self;
    5. public:
    6. ReverseIterator(Iterator it)
    7. :_it(it)
    8. {}
    9. Self& operator++()
    10. {
    11. --_it;
    12. return *this;
    13. }
    14. Self operator++(int)
    15. {
    16. Self tmp(*this);
    17. --_it;
    18. return tmp;
    19. }
    20. Self& operator--()
    21. {
    22. ++_it;
    23. return *this;
    24. }
    25. Self operator--(int)
    26. {
    27. Self tmp(*this);
    28. ++_it;
    29. return tmp;
    30. }
    31. Ref operator*()//返回前一个位置的数据
    32. {
    33. Iterator cur = _it;
    34. return *(--cur);
    35. }
    36. Ptr operator->()
    37. {
    38. return &(operator*());
    39. }
    40. bool operator!=(const Self& s)
    41. {
    42. return _it != s._it;
    43. }
    44. bool operator==(const Self& s)
    45. {
    46. return _it == s._it;
    47. }
    48. private:
    49. Iterator _it;
    50. };

    库中设计的反向迭代器与正向迭代器是对称关系,关于解引用越界问题也很巧妙的处理了~:

    解引用返回的是前一个位置的数据

     vector模拟实现:

    1. #include
    2. #include"Reverseiterator.h"
    3. namespace djx
    4. {
    5. template<class T>
    6. class vector
    7. {
    8. public:
    9. typedef T* iterator;
    10. typedef const T* const_iterator;
    11. typedef ReverseIterator reverse_iterator;
    12. typedef ReverseIteratorconst T&, const T*> const_reverse_iterator;
    13. reverse_iterator rbegin()
    14. {
    15. return reverse_iterator(end());
    16. }
    17. reverse_iterator rend()
    18. {
    19. return reverse_iterator(begin());
    20. }
    21. const_reverse_iterator rbegin() const
    22. {
    23. return const_reverse_iterator(end());
    24. }
    25. const_reverse_iterator rend() const
    26. {
    27. return const_reverse_iterator(begin());
    28. }
    29. iterator begin()
    30. {
    31. return _start;
    32. }
    33. iterator end()
    34. {
    35. return _finish;
    36. }
    37. const_iterator begin()const
    38. {
    39. return _start;
    40. }
    41. const_iterator end()const
    42. {
    43. return _finish;
    44. }
    45. vector()//一定要写,因为我们已经写了拷贝构造了,编译器不会生成默认的构造函数,当要使用无参的构造时如果我们没写,就没有,会报错
    46. {}
    47. vector(const vector& v)
    48. {
    49. reserve(v.capacity());
    50. for (auto& e : v)
    51. {
    52. push_back(e);
    53. }
    54. }
    55. vector(size_t n, const T& val = T())
    56. {
    57. reserve(n);
    58. for (size_t i = 0; i < n; i++)
    59. {
    60. push_back(val);
    61. }
    62. }
    63. template <class InputIterator>
    64. vector(InputIterator first, InputIterator last)
    65. {
    66. while (first != last)
    67. {
    68. push_back(*first);
    69. first++;
    70. }
    71. }
    72. void swap(vector& v)
    73. {
    74. std::swap(_start, v._start);
    75. std::swap(_finish, v._finish);
    76. std::swap(_endofstorage, v._endofstorage);
    77. }
    78. vector& operator=(vector tmp)
    79. {
    80. swap(tmp);
    81. return *this;
    82. }
    83. ~vector()
    84. {
    85. delete[] _start;
    86. _start = _finish = _endofstorage = nullptr;
    87. }
    88. T& operator[](size_t pos)
    89. {
    90. assert(pos < size());
    91. return _start[pos];
    92. }
    93. const T& operator[](size_t pos) const
    94. {
    95. assert(pos < size());
    96. return _start[pos];
    97. }
    98. void reserve(size_t n)
    99. {
    100. if (n > capacity())
    101. {
    102. size_t sz = size();
    103. T* tmp = new T[n];
    104. if (_start)
    105. {
    106. for (size_t i = 0; i < sz; i++)
    107. {
    108. tmp[i] = _start[i];
    109. }
    110. delete[] _start;
    111. }
    112. _start = tmp;
    113. _finish = _start + sz;
    114. _endofstorage = _start + n;
    115. }
    116. }
    117. void push_back(const T& val)
    118. {
    119. /* if (_finish == _endofstorage)
    120. {
    121. reserve(capacity() == 0 ? 4 : capacity() * 2);
    122. }
    123. *_finish = val;
    124. _finish++;*/
    125. insert(end(), val);//复用insert
    126. }
    127. void resize(size_t n, const T& val = T())
    128. {
    129. if (n <= size())
    130. {
    131. _finish = _start + n;
    132. }
    133. else
    134. {
    135. reserve(n);
    136. while (_finish < _start + n)
    137. {
    138. *_finish = val;
    139. _finish++;
    140. }
    141. }
    142. }
    143. void insert(iterator pos, const T& val)
    144. {
    145. assert(pos >= _start);
    146. assert(pos <= _finish);
    147. if (_finish == _endofstorage)
    148. {
    149. size_t len = pos - _start;
    150. reserve(capacity() == 0 ? 4 : capacity() * 2);
    151. pos = _start + len;
    152. }
    153. iterator end = _finish - 1;
    154. while (end >= pos)
    155. {
    156. *(end + 1) = *end;
    157. end--;
    158. }
    159. *pos = val;
    160. _finish++;
    161. }
    162. iterator erase(iterator pos)
    163. {
    164. assert(pos >= _start);
    165. assert(pos < _finish);
    166. iterator begin = pos + 1;
    167. while (begin < _finish)
    168. {
    169. *(begin - 1) = *begin;
    170. begin++;
    171. }
    172. _finish--;
    173. return pos;
    174. }
    175. size_t capacity() const
    176. {
    177. return _endofstorage - _start;
    178. }
    179. size_t size()const
    180. {
    181. return _finish - _start;
    182. }
    183. private:
    184. iterator _start = nullptr;//都会走构造,拷贝构造的初始化列表
    185. iterator _finish = nullptr;//给缺省值,就不用我们在构造,拷贝构造函数的初始化列表给值
    186. iterator _endofstorage = nullptr;
    187. };
    188. }

    测试vector的反向迭代器:

    1. void func(const djx::vector<int>& v)
    2. {
    3. djx::vector<int>::const_reverse_iterator rit = v.rbegin();
    4. while (rit != v.rend())
    5. {
    6. cout << *rit << " ";
    7. rit++;
    8. }
    9. cout << endl;
    10. }
    11. int main()
    12. {
    13. djx::vector<int> v;
    14. v.push_back(1);
    15. v.push_back(2);
    16. v.push_back(3);
    17. v.push_back(4);
    18. djx::vector<int>::reverse_iterator rit = v.rbegin();
    19. while (rit != v.rend())
    20. {
    21. cout << *rit << " ";
    22. rit++;
    23. }
    24. cout << endl;
    25. func(v);
    26. return 0;
    27. }

     

     

    list模拟实现:

    1. #include"Reverseiterator.h"
    2. namespace djx
    3. {
    4. template<class T>
    5. struct list_node
    6. {
    7. T _data;
    8. list_node* _prev;
    9. list_node* _next;
    10. list_node(const T& x = T())
    11. :_data(x)
    12. , _prev(nullptr)
    13. , _next(nullptr)
    14. {}
    15. };
    16. template<class T, class Ref, class Ptr>
    17. struct __list_iterator
    18. {
    19. typedef list_node Node;
    20. typedef __list_iterator self;
    21. Node* _node;
    22. __list_iterator(Node* node)
    23. :_node(node)
    24. {}
    25. Ref operator*()
    26. {
    27. return _node->_data;
    28. }
    29. Ptr operator->()
    30. {
    31. return &_node->_data;
    32. }
    33. self& operator++()
    34. {
    35. _node = _node->_next;
    36. return *this;
    37. }
    38. self operator++(int)
    39. {
    40. self tmp(*this);
    41. _node = _node->_next;
    42. return tmp;
    43. }
    44. self& operator--()
    45. {
    46. _node = _node->_prev;
    47. return *this;
    48. }
    49. self operator--(int)
    50. {
    51. self tmp(*this);
    52. _node = _node->_prev;
    53. return tmp;
    54. }
    55. bool operator!=(const self& s)
    56. {
    57. return _node != s._node;
    58. }
    59. bool operator==(const self& s)
    60. {
    61. return _node == s._node;
    62. }
    63. };
    64. template<class T>
    65. class list
    66. {
    67. typedef list_node Node;
    68. public:
    69. typedef __list_iterator iterator;
    70. typedef __list_iteratorconst T&, const T*> const_iterator;
    71. typedef ReverseIterator reverse_iterator;
    72. typedef ReverseIteratorconst T&, const T*> const_reverse_iterator;
    73. reverse_iterator rbegin()
    74. {
    75. return reverse_iterator(end());
    76. }
    77. reverse_iterator rend()
    78. {
    79. return reverse_iterator(begin());
    80. }
    81. const_reverse_iterator rbegin()const
    82. {
    83. return const_reverse_iterator(end());
    84. }
    85. const_reverse_iterator rend() const
    86. {
    87. return const_reverse_iterator(begin());
    88. }
    89. iterator begin()
    90. {
    91. return _head->_next;
    92. }
    93. iterator end()
    94. {
    95. return _head;
    96. }
    97. const_iterator begin()const
    98. {
    99. return _head->_next;
    100. }
    101. const_iterator end()const
    102. {
    103. return _head;
    104. }
    105. void empty_init()
    106. {
    107. _head = new Node;
    108. _head->_next = _head;
    109. _head->_prev = _head;
    110. _size = 0;
    111. }
    112. list()
    113. {
    114. empty_init();
    115. }
    116. list(const list& lt)
    117. {
    118. empty_init();
    119. for (auto e : lt)
    120. {
    121. push_back(e);
    122. }
    123. }
    124. void swap(list& lt)
    125. {
    126. std::swap(_head, lt._head);
    127. std::swap(_size, lt._size);
    128. }
    129. list& operator=(list lt)
    130. {
    131. swap(lt);
    132. return *this;
    133. }
    134. ~list()
    135. {
    136. clear();
    137. delete _head;
    138. _head = nullptr;
    139. }
    140. void clear()
    141. {
    142. iterator it = begin();
    143. while (it != end())
    144. {
    145. it = erase(it);
    146. }
    147. }
    148. void push_back(const T& x)
    149. {
    150. insert(end(), x);
    151. }
    152. void push_front(const T& x)
    153. {
    154. insert(begin(), x);
    155. }
    156. void pop_back()
    157. {
    158. erase(--end());
    159. }
    160. void pop_front()
    161. {
    162. erase(begin());
    163. }
    164. iterator insert(iterator pos, const T& x)
    165. {
    166. Node* cur = pos._node;
    167. Node* newnode = new Node(x);
    168. Node* prev = cur->_prev;
    169. prev->_next = newnode;
    170. newnode->_prev = prev;
    171. newnode->_next = cur;
    172. cur->_prev = newnode;
    173. _size++;
    174. return newnode;
    175. }
    176. iterator erase(iterator pos)
    177. {
    178. Node* cur = pos._node;
    179. Node* next = cur->_next;
    180. Node* prev = cur->_prev;
    181. delete cur;
    182. prev->_next = next;
    183. next->_prev = prev;
    184. _size--;
    185. return next;
    186. }
    187. size_t size()
    188. {
    189. return _size;
    190. }
    191. private:
    192. Node* _head;
    193. size_t _size;
    194. };
    195. }

    测试list的反向迭代器:

    1. void func(const djx::list<int>& lt)
    2. {
    3. djx::list<int>::const_reverse_iterator rit = lt.rbegin();
    4. while (rit != lt.rend())
    5. {
    6. cout << *rit << " ";
    7. rit++;
    8. }
    9. cout << endl;
    10. }
    11. int main()
    12. {
    13. djx::list<int> lt;
    14. lt.push_back(1);
    15. lt.push_back(2);
    16. lt.push_back(3);
    17. lt.push_back(4);
    18. djx::list<int>::reverse_iterator rit = lt.rbegin();
    19. while (rit != lt.rend())
    20. {
    21. cout << *rit << " ";
    22. rit++;
    23. }
    24. cout << endl;
    25. func(lt);
    26. return 0;
    27. }

    当然了,我们也可以按照不同于库中设计的逻辑来设计反向迭代器:但是存在一些细节需要处理

    与库中反向迭代器设计模式不同之处在于解引用的设计 

    上图版本的反向迭代器解引用重载的设计: 

    1. Ref operator*()
    2. {
    3. return *_it
    4. }

     那么,相应的在vector和list中也会发生变化:

    vector中:

    1. reverse_iterator rbegin()
    2. {
    3. return reverse_iterator(end() - 1);
    4. }
    5. reverse_iterator rend()
    6. {
    7. return reverse_iterator(begin() - 1);
    8. }
    9. const_reverse_iterator rbegin() const
    10. {
    11. return const_reverse_iterator(end() - 1);
    12. }
    13. const_reverse_iterator rend() const
    14. {
    15. return const_reverse_iterator(begin() - 1);
    16. }

    需要注意的是必须是end()-1 /begin()-1 而不能是--end()/--begin()

    因为vector类中迭代器的实现,我们将其设计为原生指针T*,是内置类型

    end()/begin() 为传值返回,返回的是临时对象,具有常性,不可被修改

    list中:

    1. reverse_iterator rbegin()
    2. {
    3. return reverse_iterator(--end());
    4. }
    5. reverse_iterator rend()
    6. {
    7. return reverse_iterator(end());
    8. }
    9. const_reverse_iterator rbegin() const
    10. {
    11. return const_reverse_iterator(--end());
    12. }
    13. const_reverse_iterator rend() const
    14. {
    15. return const_reverse_iterator(end());
    16. }

    也可以设计成end()-1,只不过list的正向迭代器是自定义类型,需要重载-运算符才可

    那么问题就来了,为什么同样是各自的--end() ,vector就报错,我们知道因为返回的是临时对象具有常性导致的,但是list却不报错可以这样设计呢?

    诚然,list的end()返回的也是临时对象,同样具有常性,不报错是因为这是特殊情况,特殊处理:具有常性的自定义类型的对象可以调用非const的函数

    所以list中的--end()返回的自定义类型的临时对象可以调用list迭代器类中,非const的--运算符重载函数

    如:

    1. class A
    2. {
    3. public:
    4. A(int x = 0)
    5. :_a(x)
    6. {}
    7. void Print()
    8. {}
    9. private:
    10. int _a;
    11. };

    我们有时候会写出这样的代码:

    A(1).Print(); // 特殊处理

    A(1)是匿名对象具有常性,而print函数是非const的 

  • 相关阅读:
    第八周复习
    如何将PDF转换为Excel?一招解决办公难题
    PHP如何切割excel大文件,使用 PHP_XLSXWriter 代替 PHPExcel 10W+ 数据秒级导出
    Vue,过滤器的了解和使用
    Centos - Mariadb Backup Script 服务搭建
    基于腾讯地图实现精准定位,实现微信小程序考勤打卡功能
    Hive基础知识概念
    ARM开发(5)ARM的接口技术(串行通信与并行通信,同步串行通信与异步串行通信,波特率,串行通信术语,uart,i2c,spi三种协议简单引入)
    mysql8配置优化
    C#可空类型
  • 原文地址:https://blog.csdn.net/weixin_73142957/article/details/133826981