C++STL反向迭代器设计
目录
- 反向迭代器
- 反向迭代器的定义
- 如何获取反向迭代器
- 反向迭代器的操作
- 反向迭代器与普通迭代器的关系
- 适配器模式
- 封装代码
反向迭代器
反向迭代器的定义
反向迭代器是一种迭代器适配器,它重新定义了递增和递减操作,使其行为在逻辑上与原始迭代器相反。
当我们对反向迭代器进行递增时,它实际上会向容器起始方向移动(即递减内部的基础迭代器);而递减则向容器末尾方向移动(递增内部的基础迭代器)。
如何获取反向迭代器
C++容器(如vector, list, deque等)提供了rbegin()和rend()成员函数,用于获取反向迭代器。
- rbegin(): 返回一个指向容器最后一个元素的反向迭代器。
- rend(): 返回一个指向容器第一个元素前一个位置的反向迭代器。
同样,还有crbegin()和crend(),它们返回常量反向迭代器。
反向迭代器的操作
反向迭代器支持与普通迭代器相似的操作,如解引用、递增、递减等。但是要注意:
解引用反向迭代器时,返回的是其内部基础迭代器前一个位置的元素的引用。这是因为反向迭代器的设计是为了提供与正向迭代器对称的行为。
具体来说,rbegin()指向最后一个元素,而rend()指向第一个元素之前,这样当使用反向迭代器遍历时,从rbegin()到rend()就相当于从最后一个元素到第一个元素。
反向迭代器与普通迭代器的关系
适配器模式
反向迭代器内部包装了一个普通迭代器(基础迭代器),并通过调整递增和递减的含义来实现反向遍历。使用了适配是的设计模式,让设计更加容易,复用率高。
注意事项:
我们在封装代码的时候,rend应返回begin(),rbegin()应返回rend()。那么在使用反向迭代器遍历的时候,解引用操作在rbegin()的时候就会解引用到end(),这样就会产生非法操作,因此我们可以在解引用的时候解引用end()–的位置,这样就可以完美避开缺陷,同时又使得迭代器与反向迭代器呈现对称关系。
封装代码
#pragma once
#include<iostream>namespace ReIterator{template <class Iterator , class Ref, class Ptr>class reverse_iterator{typedef reverse_iterator<Iterator, Ref, Ptr> Self;Iterator _reit;public:reverse_iterator(const Iterator& it = Iterator()):_reit(it){ }Self& operator++(){return --_reit;}Self operator++(int){return _reit--;}Self& operator--(){return ++_reit;}Self operator--(int){return _reit++;}Ref operator*() {Iterator tmp = _reit;return *(--tmp);}Ptr operator->() {Iterator tmp = _reit;tmp--;return tmp.operator->();}bool operator==(const Self& it) const{return _reit == it._reit;}bool operator!=(const Self& it) const{return _reit != it._reit;}};
}namespace mylist
{template <class T>struct ListNode{T _val = 0;ListNode *_next = nullptr;ListNode *_prev = nullptr;ListNode(const T &val = T()) : _val(val){}};template <class T>class list;template <class T, class Ref, class Ptr>class ListIterator{typedef ListNode<T> Node;typedef ListIterator<T, Ref, Ptr> self;Node *_node;friend class list<T>;public:ListIterator(Node *node = nullptr) : _node(node){}Ref operator*(){return _node->_val;}Ptr operator->(){return &(_node->_val);}self &operator++(){_node = _node->_next;return *this;}self operator++(int){self &tmp = *this;_node = _node->_next;return tmp;}self operator--(){_node = _node->_prev;return *this;}self &operator--(int){self &tmp = *this;_node = _node->_prev;return tmp;}bool operator==(const self &it) const{return it._node == _node;}bool operator!=(const self &it) const{return it._node != _node;}};template <class T>class list{typedef ListNode<T> Node;Node *_head = nullptr;size_t _size = 0;public:typedef ListIterator<T, T &, T *> iterator;typedef ListIterator<T, const T &, const T *> const_iterator;typedef ReIterator::reverse_iterator < iterator, T&, T*> reverse_iterator;typedef ReIterator::reverse_iterator < const_iterator, const T&, const T*> const_reverse_iterator;list(){Init();}list(size_t n, const T &val = T()){Init();while (n--){push_back(val);}}list(iterator first, iterator last){Init();while (first != last){push_back(*first);first++;}}list(const list<T> <){Init();const_iterator it = lt.cbegin();while (it != lt.cend()){push_back(*it);it++;}}void Init(){_head = new Node;_head->_next = _head;_head->_prev = _head;}iterator begin(){return _head->_next;}iterator end(){return _head;}const_iterator cbegin() const{return _head->_next;}const_iterator cend() const{return _head;}reverse_iterator rbegin(){return end();}reverse_iterator rend(){return begin();}const_reverse_iterator crbegin() const{return cend();}const_reverse_iterator crend() const{return cbegin();}const_reverse_iterator rbegin() const{return cend();}const_reverse_iterator rend() const{return cbegin();}iterator insert(iterator pos, const T &val){Node *newnode = new Node(val);Node *next = pos._node;Node *prev = next->_prev;prev->_next = newnode;newnode->_prev = prev;newnode->_next = next;next->_prev = newnode;_size++;return newnode;}iterator erase(iterator pos){assert(!empty());Node *next = pos._node->_next;Node *prev = pos._node->_prev;prev->_next = next;next->_prev = prev;delete pos._node;_size--;return next;}void push_back(const T &val){// Node *newnode = new Node(val);// if (newnode != nullptr)// {// _head->_prev->_next = newnode;// newnode->_prev = _head->_prev;// _head->_prev = newnode;// newnode->_next = _head;// }insert(end(), val);}void push_front(const T &val){insert(begin(), val);}void pop_back(){erase(--end());}void pop_front(){erase(begin());}bool empty(){return _size == 0;}size_t size(){return _size;}void print(){for (auto &e : *this){std::cout << e << " ";}std::cout << std::endl;}};}
上述代码以list为例即封装了普通的迭代器,还使用普通的迭代器适配出了反向迭代器。