C++STL反向迭代器设计
·
反向迭代器
反向迭代器的定义
反向迭代器是一种迭代器适配器,它重新定义了递增和递减操作,使其行为在逻辑上与原始迭代器相反。
当我们对反向迭代器进行递增时,它实际上会向容器起始方向移动(即递减内部的基础迭代器);而递减则向容器末尾方向移动(递增内部的基础迭代器)。

如何获取反向迭代器
C++容器(如vector, list, deque等)提供了rbegin()和rend()成员函数,用于获取反向迭代器。
- rbegin(): 返回一个指向容器最后一个元素的反向迭代器。
- rend(): 返回一个指向容器第一个元素前一个位置的反向迭代器。
同样,还有crbegin()和crend(),它们返回常量反向迭代器。
反向迭代器的操作
反向迭代器支持与普通迭代器相似的操作,如解引用、递增、递减等。但是要注意:
解引用反向迭代器时,返回的是其内部基础迭代器前一个位置的元素的引用。这是因为反向迭代器的设计是为了提供与正向迭代器对称的行为。
具体来说,rbegin()指向最后一个元素,而rend()指向第一个元素之前,这样当使用反向迭代器遍历时,从rbegin()到rend()就相当于从最后一个元素到第一个元素。
反向迭代器与普通迭代器的关系
适配器模式
反向迭代器内部包装了一个普通迭代器(基础迭代器),并通过调整递增和递减的含义来实现反向遍历。使用了适配是的设计模式,让设计更加容易,复用率高。除此之外,const迭代器也可以适配出const反向迭代器,大大提升开发效率。
注意事项:
我们在封装代码的时候,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为例即封装了普通的迭代器,还使用普通的迭代器适配出了反向迭代器。
更多推荐



所有评论(0)