反向迭代器
反向迭代器其实就是对正向迭代器的一个封装实现。那么可以说反向迭代器也是一个适配器,本文模拟实现List中的反向迭代器,具体源码我已更新至gitee中的List,有需要的读者可自信参考,如果细节错误多谢指出。
template<typename T, typename Ref, typename Ptr>
struct _list_iterator {
typedef list_node<T> node;
typedef _list_iterator<T, Ref, Ptr> self;
node* _node;
//Ref代表T& or const T&,Ptr代表T* or const T*
_list_iterator(node* n)
:_node(n)
{}
Ref operator * () {
return _node->_data;
}
Ptr operator ->() {
return &_node->_data;
}
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& s)const {
return _node == s._node;
}
bool operator !=(const self& s) const {
return !(_node == s._node);
}
};
这是我们之前模拟实现过的正向迭代器,可以复习一下
实现反向迭代器是方式有很多种,最简单最容易想到的一种就是完全复刻正向迭代器的样子,将_prev / _next互换即可,这样做的确可以,运行效率也ok,但是显得代码非常重复冗余
因此,我们可以这样想,不管什么迭代器,它无非是原生指针或是对原生指针的封装,反向迭代器亦是如此,那么对原生指针的封装再进行封装,底层依旧是原生指针,但可以简化代码,故而我们采用对正向迭代器进行进一步封装来实现反向迭代器
下面我们就来实现一个List的反向迭代器
template<typename Iterator,typename Ref,typename Ptr>
struct _list_reverse_iterator{
iterator _it; //成员属性
typedef _list_reverse_ierator<Iterator,Ref,Ptr> self;
_list_reverse_iterator(Iterator& v) //此处gitee忘写&
:_it(v);
{}
Ref operator * () {
Iterator tmp = _it;
return *(--tmp);
}
bool operator == (const self& v)const{
return v._it==_it;
}
self& operator++(){
--_it;
return *this;
}
self operator--(int){
self tmp = *this;
++_it;
return tmp;
}
//…………………………………………
}
为了追求对称性,标准库中的反向迭代器rbegin指向的位置是正向迭代器的end位置,rend指向begin位置,我们也这么做,当然你也可以不这么做
这样一来,就极大得体现了复用的思想,其实这样实现的方向迭代器还有一个极大的优势,就是这种写法适用于任何双向迭代器,恰恰突显出了C++中一直强调的泛型编程。