• 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就可以知道
  • 相关阅读:
    AngularJS Insert Update Delete Using PHP MySQL
    Simple task manager application using AngularJS PHP MySQL
    AngularJS MySQL and Bootstrap Shopping List Tutorial
    Starting out with Node.js and AngularJS
    AngularJS CRUD Example with PHP, MySQL and Material Design
    How to install KVM on Fedora 22
    Fake_AP模式下的Easy-Creds浅析
    河南公务员写古文辞职信
    AI
    政协委员:最大愿望是让小学生步行上学
  • 原文地址:https://www.cnblogs.com/BlueBlueSea/p/14510529.html
Copyright © 2020-2023  润新知