zoukankan      html  css  js  c++  java
  • 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就可以知道
  • 相关阅读:
    Selenium 中ExpectedConditions 用法说明(最全整理)
    logback的使用和logback.xml详解
    彻底征服 Spring AOP 之 实战篇
    彻底征服 Spring AOP 之 理论篇
    面试
    Java面试
    Python的数据类型与数据结构
    利用Python的 counter内置函数,统计文本中的单词数量
    python爬虫Urllib实战
    python爬虫实战一(基于正则表达式学习)
  • 原文地址:https://www.cnblogs.com/BlueBlueSea/p/14510529.html
Copyright © 2011-2022 走看看