1.介绍
STL中迭代器是连接算法和容器的工具,迭代器可以在不了解容器内部原理的情况下遍历容器。
2.迭代器的实现
迭代器要遍历容器的元素,所以它内部必须封装一个与容器类型相关联的指针,通过重载++、--、*等操作符实现迭代器操作。
迭代器是一个类模板,主要包括一个指针,可以包含各种类型的元素,根据容器的不同,++、--等操作实现也会不同。
3.迭代器型别
迭代器的5个型别,它主要是根据实现的迭代器类来萃取它的类别,通过iterator_traits<Iter>:: iterator_category可以获取到在自定义的Iter中迭代器的类型。
template <class Iterator> struct iterator_traits{ typedef typename Iterator::iterator_category iterator_category;//迭代器的分类 typedef typename Iterator::value_type value_type;//表示迭代器所指对象的类型 typedef typename Iterator::pointer pointer;//指向迭代器所指的对象 typedef typename Iterator::reference reference;//迭代器所指对象的引用,也就是从迭代器可以返回引用? typedef typename Iterator::difference_type difference_type;//两个迭代器之间的距离 };
迭代器的5个标签:
struct input_iterator_tag{};//只读 struct output_iterator_tag{};//只写 struct forward_iterator_tag:public input_iterator_tag{};//前向移动 struct bidirectional_iterator_tag:public forward_iterator_tag{};//双向移动 struct random_access_iterator_tag:public bidirectional_iterator_tag{};//随机访问
主要是用来实现重载,确定使用什么迭代器进行操作,STL中举了例子,advance操作可以通过++前向、双向迭代器、+n随机迭代器实现,那么有了这个标签就可以在编译时确定使用什么操作。
STL中结构体的定义:
template<class _Category, class _Ty, class _Diff = ptrdiff_t, class _Pointer = _Ty *, class _Reference = _Ty&> struct iterator { // base type for iterator classes typedef _Category iterator_category; typedef _Ty value_type; typedef _Diff difference_type; typedef _Diff distance_type; // retained typedef _Pointer pointer; typedef _Reference reference; };
实现的例子,http://www.cppblog.com/hitme/archive/2009/08/20/93884.aspx,实现vector的随即随机遍历迭代器。
template<typename T> class Obj_iterator : public std::iterator <std::random_access_iterator_tag , T> //继承了iterator,并指定迭代器类型与数据类型 { protected: private://我将这个私有部分提到了前面来,它维护了一个指针 Obj<T> *m_Obj;//指针用来遍历容器对象 size_t m_index;//指针所指的位置长度 public: Obj_iterator() : m_Obj(NULL) , m_index(0) {} Obj_iterator( Obj<T> *p , size_t index ) : m_Obj(p) , m_index(index){}//构造函数完成对数据成员的初始化 Obj_iterator& operator = ( const Obj_iterator &t ) {//重载赋值操作 m_index = t.m_index; m_Obj = t.m_Obj; return *this; } bool operator ==( const Obj_iterator &rh ) const {//重载判等操作 return rh.m_Obj == m_Obj && rh.m_index == m_index; } bool operator !=( const Obj_iterator &rh ) const { return !( *this == rh ); } Obj_iterator operator ++() {//重载前自增操作 ++m_index; return Obj_iterator(m_Obj,m_index); } Obj_iterator operator ++( int ) {//重载后++操作 Obj_iterator x = *this; ++(*this); return x; } Obj_iterator operator -- () { --m_index; return Obj_iterator(m_Obj , m_index); } T& operator *() const//重载取内容操作 { return (*m_Obj)[m_index]; } T* operator ->() const { return &(*m_Obj[m_index]); } //这个实现+n,也就是随机访问操作,如果只是前向迭代器的话,不会重载这个函数 const Obj_iterator operator +(size_t n) { return Obj_iterator(m_Obj , m_index + n); } //重载+=操作 const Obj_iterator operator += (size_t n) { m_index += n; return *this; } difference_type operator -(const Obj_iterator &n) { return m_index - n.m_index; } Obj_iterator operator -(size_t n) { return Obj_iterator(m_Obj , m_index-n); } bool operator < (const Obj_iterator n) const { return m_index<n.m_index; } };
那么实现容器:
template <typename T> class Obj { public: typedef Obj_iterator<T> iterator;//定义iterator类型 iterator begin() { return iterator(this,0); } iterator end() { return iterator(this,m_sumsize); } .... //如果有计算长度的函数,那么返回类型就是iterator_traits<iterator>::difference_type };
4.不同容器的迭代器
https://docs.microsoft.com/en-us/cpp/standard-library/random-access-iterator-tag-struct?view=msvc-160
iterator_traits<vector<int>:: iterator>::iterator_category cati; iterator_traits<vector<char>:: iterator>::iterator_category catc; iterator_traits<list<char>:: iterator>::iterator_category catlc; #输出: struct std::random_access_iterator_tag struct std::random_access_iterator_tag struct std::bidirectional_iterator_tag
对原生内置类型也有特化迭代器型别:
template <class T> struct iterator_traits<T*>{ typedef std::random_access_iterator_tag iterator_category; typedef T value_type; typedef T* pointer; typedef T& reference; typedef ptrdiff_t difference_type; };
5.iterator_traits、iterator、vecIter、vector关系
https://blog.csdn.net/XiaoHeiBlack/article/details/77014626
在实现特定类型容器的时候,会继承iterator结构体,并且指定迭代器类型与数据类型:
template<class T>
class MyIterator : public iterator<input_iterator_tag, T>{ .... }
在实现容器时,内部会用typefdef对应一个迭代器类型:
template<class T> class myVector{ public: typedef MyIterator<T> iterator; ... };
对迭代器的型别访问就是通过iterator_traits来实现的,
比如说有一个函数要计算给定迭代器区间内某个元素出现的次数:
// TEMPLATE FUNCTION count_if template<class _InIt, class _Pr> inline typename iterator_traits<_InIt>::difference_type//返回类型 _Count_if(_InIt _First, _InIt _Last, _Pr _Pred) { // count elements satisfying _Pred typename iterator_traits<_InIt>::difference_type _Count = 0; for (; _First != _Last; ++_First) if (_Pred(*_First)) ++_Count; return (_Count); } //在调用时: myVector<int> mv(10); mv[3] = 10; mv[9] = 10; myVector<int>::iterator it = mv.begin(); cout << count_if(mv.begin(), mv.end(), eq_10) << endl; //那么count_if函数获取到的第一个类型_InIt就是myVector<int>::iterator类型,即MyIterator<T> //那么iterator_traits<MyIterator<T>>::difference_type就可以知道