STL 迭代器学习

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就可以知道
原文地址:https://www.cnblogs.com/BlueBlueSea/p/14510529.html