• STL源码分析--iterator


    更多精彩内容,请关注微信公众号:后端技术小屋

    1 相关头文件

    iterator
    iterator.h 
    stl_iterator.h
    stl_iterator_base.h 
    

    2 输入迭代器

    2.1 iterator的种类

    在STL中,迭代器分为输入迭代器、输出迭代器、前向迭代器、双向迭代器、随机访问迭代器。这里先讲输入迭代器这个大类。

    • 输入迭代器: input_iterator
      输入迭代器指向的位置只能被顺序读取(iterator_category类型为input_iterator_tag)。在每种迭代器类型中,必须定义iterator_category表示迭代器种类,value_type表示迭代器指向的实例类型,difference_type表示迭代器距离的类型,pointer表示迭代器指向的实例的指针类型,reference表示实例应用类型。
    template <class _Tp, class _Distance> struct input_iterator {
      typedef input_iterator_tag iterator_category;
      typedef _Tp                value_type;
      typedef _Distance          difference_type;
      typedef _Tp*               pointer;
      typedef _Tp&               reference;
    };
    
    • 输出迭代器:ouput_iterator
      输出迭代器指向的位置只能被顺序写入(iterator_category类型为output_iterator_tag)
    struct output_iterator {
      typedef output_iterator_tag iterator_category;
      typedef void                value_type;
      typedef void                difference_type;
      typedef void                pointer;
      typedef void                reference;
    };
    
    • 前向迭代器: forward_iterator
      前向迭代器只能自增不能自减,它是一种特殊的输入迭代器(iterator_category类型为forward_iterator_tag,而后者正是input_iterator_tag的派生类)
    template <class _Tp, class _Distance> struct forward_iterator {
      typedef forward_iterator_tag iterator_category;
      typedef _Tp                  value_type;
      typedef _Distance            difference_type;
      typedef _Tp*                 pointer;
      typedef _Tp&                 reference;
    };
    
    
    struct forward_iterator_tag : public input_iterator_tag {};
    
    • 双向迭代器:bidirectional_iterator
      双向迭代器既能自增,又能自减,它是一种特殊的前向迭代器(能够自减的前向迭代器)。注意iterator_category类型为bidirectional_iterator_tag,而后者正是forward_iterator_tag的派生类。
    template <class _Tp, class _Distance> struct bidirectional_iterator {
      typedef bidirectional_iterator_tag iterator_category;
      typedef _Tp                        value_type;
      typedef _Distance                  difference_type;
      typedef _Tp*                       pointer;
      typedef _Tp&                       reference;
    };
    
    
    struct bidirectional_iterator_tag : public forward_iterator_tag {};
    
    • 随机访问迭代器:random_access_iterator
      随机访问迭代器,是一种特殊的双向迭代器,除了自增自减1之外,还能自增自减n。注意iterator_category类型为random_access_iterator_tag,而后者正是bidirectional_iterator_tag的派生类。
    template <class _Tp, class _Distance> struct random_access_iterator {
      typedef random_access_iterator_tag iterator_category;
      typedef _Tp                        value_type;
      typedef _Distance                  difference_type;
      typedef _Tp*                       pointer;
      typedef _Tp&                       reference;
    };
    

    2.2 iterator类型萃取

    作用:将不同种类迭代器中定义的iterator_category, value_type, difference_type, pointer, reference类型转化为萃取器自身的类型。当上层调用萃取器iterator_traits时,迭代器类型(作为iterator_traits的模板参数)对上层是透明的。

    实现如下,由于2.1中所有迭代器中,都定义了iterator_category等类型,iterator_traits便可将迭代器中的类型导出作为自身类型。

    template <class _Iterator>
    struct iterator_traits {
      typedef typename _Iterator::iterator_category iterator_category;
      typedef typename _Iterator::value_type        value_type;
      typedef typename _Iterator::difference_type   difference_type;
      typedef typename _Iterator::pointer           pointer;
      typedef typename _Iterator::reference         reference;
    };
    

    某些特殊情况下,原始指针_Tp*也可作为iterator使用(例如数组中的原始指针)。因为_Tp*内部并未定义以上类型,因此iterator_traits需要对_Tp*const _Tp*进行特化。

    template <class _Tp>
    struct iterator_traits<_Tp*> {
      typedef random_access_iterator_tag iterator_category;
      typedef _Tp                         value_type;
      typedef ptrdiff_t                   difference_type;
      typedef _Tp*                        pointer;
      typedef _Tp&                        reference;
    };
    
    
    template <class _Tp>
    struct iterator_traits<const _Tp*> {
      typedef random_access_iterator_tag iterator_category;
      typedef _Tp                         value_type;
      typedef ptrdiff_t                   difference_type;
      typedef const _Tp*                  pointer;
      typedef const _Tp&                  reference;
    };
    

    有了iterator_traits,迭代器操作便可根据不同的类型进行不同的实现。

    2.3 iterator_category函数(返回迭代器种类)

    实现如下,模板入参为迭代器,iterator_category函数所返回的是迭代器中iterator_category类型的实例。

    template <class _Iter>
    inline typename iterator_traits<_Iter>::iterator_category
    iterator_category(const _Iter& __i) { return __iterator_category(__i); }
    
    
    template <class _Iter>
    inline typename iterator_traits<_Iter>::iterator_category
    __iterator_category(const _Iter&)
    {
      typedef typename iterator_traits<_Iter>::iterator_category _Category;
      return _Category();
    }
    

    2.4 distance函数(返回两迭代器之间距离)

    实现如下,首先通过iterator_category函数获取迭代器种类,再将其值作为参数传给__distance函数。

    template <class _InputIterator, class _Distance>
    inline void distance(_InputIterator __first, 
                         _InputIterator __last, _Distance& __n)
    {
      __STL_REQUIRES(_InputIterator, _InputIterator);
      __distance(__first, __last, __n, iterator_category(__first));
    }
    

    返回结果关键在于__distance函数。对于不同的迭代器类型,重载了不同的__distance实现,这些实现使用了迭代器中的iterator_category类型进行区分。

    例如:对于随机访问迭代器类型,计算distance只需将两个迭代器相减即可。

    template <class _RandomAccessIterator, class _Distance>
    inline void __distance(_RandomAccessIterator __first, 
                           _RandomAccessIterator __last, 
                           _Distance& __n, random_access_iterator_tag)
    {
      __STL_REQUIRES(_RandomAccessIterator, _RandomAccessIterator);
      __n += __last - __first;
    }
    

    对于其他迭代器(都属于input_iterator类型),实现上则需要从__first步步递进并计数,直到到达__last为止,最后返回计数值

    template <class _InputIterator, class _Distance>
    inline void __distance(_InputIterator __first, _InputIterator __last,
                           _Distance& __n, input_iterator_tag)
    {
      while (__first != __last) { ++__first; ++__n; }
    }
    

    2.5 advance函数(迭代器偏移n个位置)

    对于advance函数, 不同类型迭代器其实现也不尽相同。

    • random_access_iterator:随机访问迭代器支持一次跳转多步,因此可一次跳转至目标位置
    • bidirectional_iterator: 双向迭代器同时支持前向自增1和后向自增1。如果n>=0, 迭代器重复执行n次自增1, 如果n<0, 迭代器重复执行-n次自减1
    • input_iterator: 输入迭代器只能支持前向自增1。n必须大于等于零,此时迭代器执行n次自增1。
    template <class _InputIterator, class _Distance>
    inline void advance(_InputIterator& __i, _Distance __n) {
      __STL_REQUIRES(_InputIterator, _InputIterator);
      __advance(__i, __n, iterator_category(__i));
    }
    
    
    template <class _RandomAccessIterator, class _Distance>
    inline void __advance(_RandomAccessIterator& __i, _Distance __n, 
                          random_access_iterator_tag) {
      __STL_REQUIRES(_RandomAccessIterator, _RandomAccessIterator);
      __i += __n;
    }
    
    
    template <class _BidirectionalIterator, class _Distance>
    inline void __advance(_BidirectionalIterator& __i, _Distance __n, 
                          bidirectional_iterator_tag) {
      __STL_REQUIRES(_BidirectionalIterator, _BidirectionalIterator);
      if (__n >= 0)
        while (__n--) ++__i;
      else
        while (__n++) --__i;
    }
    
    
    
    template <class _InputIter, class _Distance>
    inline void __advance(_InputIter& __i, _Distance __n, input_iterator_tag) {
      while (__n--) ++__i;
    }
    

    2.6 反向迭代器

    反向迭代器一般用于逆向遍历容器。其自增和自减的方向与其封装的迭代器正好是反过来的。

      iterator_type base() const { return current; }
      reference operator*() const {
        _Iterator __tmp = current;
        return *--__tmp;
      }
    
    
      _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;
      }
    
    
    

    构造时,输入类型为_Iterator的迭代器对象__x, reverse_iterator<_Iterator>即为_Iterator的逆操作。API如下:

    • base: 返回被封装的__x迭代器
    • operator*: 返回*(__x-1) (容器的end iterator为虚边界,当基于end iterator生成反向迭代器时,执行operator*应当返回容器的最后一个元素)
    • operator++: __x自减1
    • operator--: __x自增1

    3 输出迭代器

    back_inserter_iterator, front_insert_iterator, insert_iterator中都定义了iterator_category类型为output_iterator_tag。因此它们都是输出迭代器。

    back_insert_iterator为例,其中模板参数_Container为STL容器类型,iterator_categoryoutput_iterator_tag类型。

    template <class _Container>
    class back_insert_iterator {
    protected:
      _Container* container;
    public:
      typedef _Container          container_type;
      typedef output_iterator_tag iterator_category;
      ...
    };
    

    3.1 back_insert_iterator

    用于向容器尾部插入元素

      back_insert_iterator<_Container>&
      operator=(const typename _Container::value_type& __value) { 
        container->push_back(__value);
        return *this;
      }
    

    back_inserter_iterator执行operator=操作时,总是对容器push_back(容器必须实现push_back接口)

    3.2 front_insert_iterator

    用于向容器头部插入元素

      explicit front_insert_iterator(_Container& __x) : container(&__x) {}
      front_insert_iterator<_Container>&
      operator=(const typename _Container::value_type& __value) { 
        container->push_front(__value);
        return *this;
    

    front_inserter_iterator执行operator=操作时,总是对容器push_front(容器必须实现push_front接口)

    3.3 insert_iterator

    用于向容器指定位置插入元素

    
    
      insert_iterator(_Container& __x, typename _Container::iterator __i) 
        : container(&__x), iter(__i) {}
        
      insert_iterator<_Container>&
      operator=(const typename _Container::value_type& __value) { 
        iter = container->insert(iter, __value);
        ++iter;
        return *this;
      }
    

    insert_iterator构造时传入容器和迭代器iter,执行operator=操作时,总是对容器执行insert, 插入位置由迭代器iter决定(容器必须实现insert接口)

    推荐阅读

    更多精彩内容,请扫码关注微信公众号:后端技术小屋。如果觉得文章对你有帮助的话,请多多分享、转发、在看。
    二维码

  • 相关阅读:
    [读书笔记]黑客与画家[Hackers.and.Painters]
    android电池充电以及电量检测驱动分析
    LV在系统重启后不能自动激活(boot.lvm&after.loca)
    线段树菜鸟一题+归并排序【求逆序数】POJ2299
    【PAT】1035. Password (20)
    Android应用开发学习笔记之ContentProvider
    UVAlive 2322 Wooden Sticks(贪心)
    卸载QTP
    线段树模板
    2013 CSU校队选拔赛(1) 部分题解
  • 原文地址:https://www.cnblogs.com/taiyang-li/p/14450505.html
Copyright © 2020-2023  润新知