什么是迭代器?
迭代器(iterator)有时又称光标(cursor)是程序设计的软件设计模式,可在容器对象(container,例如list或vector)上遍历访问的接口,通常来说就是访问容器(数据结构中保存)的元素。并且迭代器是分类型的,STL中的名字是类型的暗示(比如Inputiterator),迭代器的使用属性是正向访问以及反向访问;还有特性属性,严格来说还分单向双向随机,单链表的迭代器特性就是一个单向的,它只能++,不能--,双向链表的迭代器特性就是双向的,不仅能++,还能--。随机就是不仅能++,--,还能+,-,像string,vector就是随机的特性。
注:
iterator:迭代器/正向迭代器
reverse_iterator:反向迭代器
const_iterator:const迭代器/const正向迭代器
const_reverse_iterator:const反向迭代器
反向迭代器的实现:
以 list 的迭代器为例:建议先看一下list迭代器的底层,再来看此文章会更通俗易懂。
list.h - iterator的实现:
template<class T, class Ref, class Ptr>struct __list_iterator{public:typedef list_node<T> node;typedef __list_iterator<T, Ref, Ptr> self;node* _node;__list_iterator(node* x):_node(x){}Ptr operator->(){return &_node->_data;}Ref operator*(){return _node->_data;}self& operator++(){_node = _node->_next;return *this;}bool operator!=(const self& s){return _node != s._node;}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){return _node == s._node;}};
这里实现正向迭代器的逻辑是左闭右开:
所以我们认为反向也应该是如此左闭右开:从最后一个有效元素开始访问,反向的++就是正向的--
这里怎样实现呢?很简单,再写一个类,修改下正向迭代器就可以了:
list.h - reverse_iterator① 的实现:
template<class T, class Ref, class Ptr>struct __list_reverse_iterator{public:typedef list_node<T> node;typedef __list_reverse_iterator<T, Ref, Ptr> self;node* _node;__list_reverse_iterator(node* x):_node(x){}Ptr operator->(){return &_node->_data;}Ref operator*(){return _node->_data;}self& operator++(){_node = _node->_prev;return *this;}bool operator!=(const self& s){return _node != s._node;}self& operator++(int){self tmp(*this);_node = _node->_prev;return tmp;}self& operator--(){_node = _node->_next;return *this;}self& operator--(int){self tmp(*this);_node = _node->_next;return tmp;}bool operator==(const self& s){return _node == s._node;}
这里我们会发现有大量重复的代码,而c++又很讨厌这种代码的臃肿性,所以这里可以看一下stl的底层:
stl源码:
stl_list.h部分源码
template <class T, class Alloc = alloc>
class list {
protected:typedef void* void_pointer;typedef __list_node<T> list_node;typedef simple_alloc<list_node, Alloc> list_node_allocator;
public: typedef T value_type;typedef value_type* pointer;typedef const value_type* const_pointer;typedef value_type& reference;typedef const value_type& const_reference;typedef list_node* link_type;typedef size_t size_type;typedef ptrdiff_t difference_type;public:typedef __list_iterator<T, T&, T*> iterator;typedef __list_iterator<T, const T&, const T*> const_iterator;#ifdef __STL_CLASS_PARTIAL_SPECIALIZATIONtypedef reverse_iterator<const_iterator> const_reverse_iterator;typedef reverse_iterator<iterator> reverse_iterator;
#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */typedef reverse_bidirectional_iterator<const_iterator, value_type,const_reference, difference_type>const_reverse_iterator;typedef reverse_bidirectional_iterator<iterator, value_type, reference,difference_type>reverse_iterator;
#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
这里可以发现,c++是使用类模板封装了正向迭代器,这里我们再继续往下看:
stl_iterator.h部分源码
template <class Iterator>
class reverse_iterator
{
protected:Iterator current;
public:typedef typename iterator_traits<Iterator>::iterator_categoryiterator_category;typedef typename iterator_traits<Iterator>::value_typevalue_type;typedef typename iterator_traits<Iterator>::difference_typedifference_type;typedef typename iterator_traits<Iterator>::pointerpointer;typedef typename iterator_traits<Iterator>::referencereference;typedef Iterator iterator_type;typedef reverse_iterator<Iterator> self;public:reverse_iterator() {}explicit reverse_iterator(iterator_type x) : current(x) {}reverse_iterator(const self& x) : current(x.current) {}
#ifdef __STL_MEMBER_TEMPLATEStemplate <class Iter>reverse_iterator(const reverse_iterator<Iter>& x) : current(x.current) {}
#endif /* __STL_MEMBER_TEMPLATES */iterator_type base() const { return current; }reference operator*() const {Iterator tmp = current;return *--tmp;}#ifndef __SGI_STL_NO_ARROW_OPERATORpointer operator->() const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_OPERATOR */self& operator++() {--current;return *this;}self operator++(int) {self tmp = *this;--current;return tmp;}self& operator--() {++current;return *this;}self operator--(int) {self tmp = *this;++current;return tmp;}self operator+(difference_type n) const {return self(current - n);}self& operator+=(difference_type n) {current -= n;return *this;}self operator-(difference_type n) const {return self(current + n);}self& operator-=(difference_type n) {current += n;return *this;}reference operator[](difference_type n) const { return *(*this + n); }
};
可以看到stl底层 reverse_iterator 的实现,其实是使用了正向迭代器来进行封装,反向迭代器的 ++ 就是正向迭代器的 -- ,反向迭代器的 -- 就是正向迭代器的 ++ 。
stl_list.h部分源码
protected:link_type node;public:list() { empty_initialize(); }iterator begin() { return (link_type)((*node).next); //node是头指针,也就是_head}const_iterator begin() const { return (link_type)((*node).next); }iterator end() { return node; //头指针}const_iterator end() const { return node; }reverse_iterator rbegin() { return reverse_iterator(end()); }const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }reverse_iterator rend() { return reverse_iterator(begin()); }const_reverse_iterator rend() const { return const_reverse_iterator(begin());}
这时,我们发现,stl 底层 rbegin() 与 rend() 的位置与我们预料的不同:
我们实现的:rbegin() 是在最后一个有效数据位
实际上 stl 底层库:
这里很明显,c++更追求一种对称的效果,那么这样的话,在实现 operator*() 的时候就不能按照我们的思路,先来看看底层stl是怎样实现的:
这里我们会发现,stl 库里在实现 operator*() 的时候,返回的是迭代器当前位置的前一个位置
所以接下来我们需要重新实现一个类:因为stl 库里面是采用萃取来实现,太过于复杂,这里实现方式不同,我采用的是新增模板参数。
reverse_iterator.h
template<class Iterator, class Ref, class Ptr>struct ReverseIterator //为了和库里进行区分,选择驼峰法{typedef ReverseIterator<Iterator, Ref, Ptr> Self;Iterator _cur;ReverseIterator(Iterator it):_cur(it){}Ref operator*(){Iterator tmp = _cur;--tmp;return *tmp;}Self& operator++(){--_cur;return *this;}Self& operator--(){++_cur;return *this;}bool operator!=(const Self& s){return _cur != s._cur;}Self& operator++(int){Self tmp(*this);--_cur;return tmp;}Self& operator--(int){Self tmp(*this);++_cur;return tmp;}bool operator==(const Self& s){return _cur == s._cur;}};
写到这里,也许很多人都会有一个疑问,这也是实现一个类,好像跟reverse_iterator①没有什么不同,代码上并没有节省,还不如reverse_iterator① 来的更通俗易懂,为什么要如此大费周章?
其实这里反向迭代器采用适配器的模式其实是为了复用,仔细想想list 的反向迭代器可以拷贝一份正向迭代器进行修改,那vector呢(注:具体可以查看vector的底层实现,这里iterator采用的原生指针),而实现 reverse_iterator.h 不仅仅是list可以使用,在这里只要是任何一个双向迭代器的容器都可以进行复用 。例如:
至此,我们需要明白反向迭代器就是正向迭代器,不过是用类来进行封装。反向迭代器去封装正向迭代器,跟正向迭代器去封装指针没有任何本质的区别,物理空间上没都没有进行改变,都是对应那个地址,只是类型决定了是正向还是反向,而类型里面的 operator++() ,operator--() , operator*() ,这些都是根据使用者的需求来定义的,这套类的规则是使用者来定义的。
附上所有示例代码:
reverse_iterator.h
#pragma oncenamespace dwr
{template<class Iterator, class Ref, class Ptr>struct ReverseIterator //为了和库里进行区分,选择驼峰法{typedef ReverseIterator<Iterator, Ref, Ptr> Self;Iterator _cur;ReverseIterator(Iterator it):_cur(it){}Ref operator*(){Iterator tmp = _cur;--tmp;return *tmp;}Self& operator++(){--_cur;return *this;}Self& operator--(){++_cur;return *this;}bool operator!=(const Self& s){return _cur != s._cur;}Self& operator++(int){Self tmp(*this);--_cur;return tmp;}Self& operator--(int){Self tmp(*this);++_cur;return tmp;}bool operator==(const Self& s){return _cur == s._cur;}};}
list.h
#pragma once
#include "reverse_iterator.h"
namespace dwr
{template<class T>struct list_node //链表节点{list_node<T>* _prev;list_node<T>* _next;T _data;list_node(const T& x = T()):_prev(nullptr), _next(nullptr), _data(x){}};template<class T, class Ref, class Ptr>struct __list_iterator{public:typedef list_node<T> node;typedef __list_iterator<T, Ref, Ptr> self;node* _node;__list_iterator(node* x):_node(x){}Ptr operator->(){return &_node->_data;}Ref operator*(){return _node->_data;}self& operator++(){_node = _node->_next;return *this;}bool operator!=(const self& s){return _node != s._node;}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){return _node == s._node;}};/*template<class T, class Ref, class Ptr>struct __list_reverse_iterator{public:typedef list_node<T> node;typedef __list_reverse_iterator<T, Ref, Ptr> self;node* _node;__list_reverse_iterator(node* x):_node(x){}Ptr operator->(){return &_node->_data;}Ref operator*(){return _node->_data;}self& operator++(){_node = _node->_prev;return *this;}bool operator!=(const self& s){return _node != s._node;}self& operator++(int){self tmp(*this);_node = _node->_prev;return tmp;}self& operator--(){_node = _node->_next;return *this;}self& operator--(int){self tmp(*this);_node = _node->_next;return tmp;}bool operator==(const self& s){return _node == s._node;}};*/template<class T>class list{typedef list_node<T> node;public:typedef __list_iterator<T, T&, T*> iterator;typedef __list_iterator<T, const T&, const T*> const_iterator;//typedef __list_reverse_iterator<T, T&, T*> reverse_iterator;typedef ReverseIterator<iterator, T&, T*> reverse_iterator;typedef ReverseIterator<iterator, const T&, const T*> const_reverse_iterator;reverse_iterator rbegin(){reverse_iterator tmp(end());return tmp;}reverse_iterator rend(){return reverse_iterator(begin());}/*reverse_iterator rbegin(){reverse_iterator tmp(_head->_prev);return tmp;}reverse_iterator rend(){return reverse_iterator(_head);}*/void empty_init() //初始化头节点{_head = new node;_head->_next = _head;_head->_prev = _head;}list(){empty_init();}void swap(list<T>& tmp){std::swap(_head, tmp._head);}//现代写法list(const list<T>& lt){empty_init();list<T> tmp(lt.begin(), lt.end());swap(tmp);}template<class Iterator>list(Iterator first, Iterator last){empty_init();while (first != last){push_back(*first);first++;}}//lt2 = lt1list<T>& operator=(list<T> lt){swap(lt);return *this;}iterator begin(){iterator tmp(_head->_next);return tmp;}iterator end(){return iterator(_head);}const_iterator begin() const{const_iterator tmp(_head->_next);return tmp;}const_iterator end() const{return const_iterator(_head);}void push_back(const T& x){node* tail = _head->_prev;node* newnode = new node(x);tail->_next = newnode;newnode->_prev = tail;newnode->_next = _head;_head->_prev = newnode;}void push_front(const T& x){insert(begin(), x);}void pop_back(){erase(--end());}void pop_front(){erase(begin());}iterator erase(iterator pos){assert(pos != end());node* next = pos._node->_next;node* prev = pos._node->_prev;next->_prev = prev;prev->_next = next;delete pos._node;return iterator(next);}void insert(iterator pos, const T& x){node* cur = pos._node;node* prev = cur->_prev;node* new_node = new node(x);prev->_next = new_node;new_node->_next = cur;new_node->_prev = prev;cur->_prev = new_node;}void clear(){iterator it = begin();while (it != end()){erase(it++);}}~list(){clear();delete _head;_head = nullptr;}private:node* _head;};//------------------------------------------------void print_list(const list<int>& lt){list<int>::const_iterator it = lt.begin();while (it != lt.end()){//(*it) *= 2;cout << *it << " ";++it;}cout << endl;}void list_test1(){list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.push_back(5);list<int>::iterator it = lt.begin();while (it != lt.end()){cout << *it << " ";++it;}cout << endl;}void list_test2(){list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.push_back(5);list<int>::reverse_iterator rit = lt.rbegin();while (rit != lt.rend()){cout << *rit << " ";++rit;}cout << endl;}
}
vector.h
#pragma once#include "reverse_iterator.h"
namespace dwr
{template <class T>class vector{public:typedef T* iterator;typedef const T* const_iterator;typedef ReverseIterator<iterator, T&, T*> reverse_iterator;typedef ReverseIterator<iterator, const T&, const T*> const_reverse_iterator;reverse_iterator rbegin(){reverse_iterator tmp(end());return tmp;}reverse_iterator rend(){return reverse_iterator(begin());}iterator begin(){return _start;}iterator end(){return _finish;}const_iterator begin() const{return _start;}const_iterator end() const{return _finish;}vector(){}vector(size_t n, const T& val = T()){reserve(n);for (size_t i = 0; i < n; ++i){push_back(val);}}vector(int n, const T& val = T()){reserve(n);for (int i = 0; i < n; ++i){push_back(val);}}//[first,last)template<class InputIterator>vector(InputIterator first, InputIterator last){while (first != last){push_back(*first);first++;}}void reserve(size_t n){if (n > capacity()){T* tmp = new T[n];size_t sz = size();if (_start){for (size_t i = 0; i < sz; ++i){tmp[i] = _start[i];}delete[] _start;}_start = tmp;_finish = _start + sz;_end_of_storage = _start + n;}}void resize(size_t n, T val = T()){if (n < size()){//删除数据_finish = _start + n;}else{if (n > capacity()){reserve(n);}while (_finish != _start + n){//注:这里如果实现逻辑是使用内存池,需要使用定位new来对已有空间进行初始化*_finish = val;++_finish;}}}iterator insert(iterator& pos, const T& val){assert(pos >= _start && pos <= _finish);if (_finish == _end_of_storage){size_t len = pos - _start;reserve(capacity() == 0 ? 4 : capacity() * 2);//扩容后 更新pospos = pos + len;}iterator end = _finish - 1;while (end >= pos){*(end + 1) = *end;--end;}*pos = val;_finish++;return pos;}iterator erase(iterator pos){assert(pos >= _start && pos <= _finish);iterator remove = pos + 1;while (remove != _finish){*(remove - 1) = remove;remove++;}--_finish;return pos;}void push_back(const T& x){if (_finish == _end_of_storage){reserve(capacity() == 0 ? 4 : capacity() * 2);}*_finish = x;_finish++;}void pop_back(){assert(!empty());--_finish;}bool empty(){return _start == _finish;}T& operator[](size_t pos){assert(pos < size());return _start[pos];}const T& operator[](size_t pos) const{assert(pos < size());return _start[pos];}size_t size() const{return _finish - _start;}size_t capacity() const{return _end_of_storage - _start;}void swap(vector<T>& v){std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_end_of_storage, v._end_of_storage);}vector<T>& operator=(vector<T> v){swap(v);return *this;}vector(const vector<T>& v){_start = new T[v.capacity()];for (size_t i = 0; i < v.size(); ++i){_start[i] = v._start[i];}_finish = _start + v.size();_end_of_storage = _start + v.capacity();}//vector(const vector<T>& v)//{// vector<T> tmp(v.begin(), v.end());// swap(tmp);//}~vector(){//cout << _start << endl;delete[] _start;_start = _finish = _end_of_storage;}private:iterator _start = nullptr;iterator _finish = nullptr;iterator _end_of_storage = nullptr;};void test_vector(){vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);for (auto e : v){cout << e << " ";}cout << endl;for (size_t i = 0; i < v.size(); ++i){cout << v[i] << " ";}cout << endl;vector<int>::iterator it = v.begin();while (it != v.end()){cout << *it << " ";++it;}cout << endl;}void test_vector2(){vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);vector<int>::reverse_iterator rit = v.rbegin();while (rit != v.rend()){cout << *rit << " ";++rit;}cout << endl;}}
test.cpp
#include <iostream>#include <assert.h>#include <vector>#include <list>#include <algorithm>using namespace std;#include "list.h"#include "vector.h"#include "reverse_iterator.h"int main()
{dwr::list_test();dwr::test_vector();dwr::list_test2();dwr::test_vector2();return 0;
}
以上仅代表个人观点,欢迎讨论