STL标准库-迭代器适配器

技术在于交流、沟通,本文为博主原创文章转载请注明出处并保持作品的完整性

这次主要介绍一下迭代器适配器.以reverse_iterator(反向迭代器),insert_iterator(插入迭代器),ostream_iterator(输出迭代器)迭代器和算法中的copy函数做参考

迭代器适配器主要运用包含及操作符重载实现(主要操作符重载有operator*,operator=,operator++,operator--)

其实本节主要就是介绍运算符重载


 

1.reverse_iterator反向迭代器的实现

下面是reverse_iterator的源码

template
    class reverse_iterator
    : public iterator::iterator_category,
              typename iterator_traits<_Iterator>::value_type,
              typename iterator_traits<_Iterator>::difference_type,
              typename iterator_traits<_Iterator>::pointer,
                      typename iterator_traits<_Iterator>::reference>
    {
    protected:
      _Iterator current;

      typedef iterator_traits<_Iterator>        __traits_type;

    public:
      typedef _Iterator                    iterator_type;
      typedef typename __traits_type::difference_type    difference_type;
      typedef typename __traits_type::pointer        pointer;
      typedef typename __traits_type::reference        reference;

      /**
       *  The default constructor value-initializes member @p current.
       *  If it is a pointer, that means it is zero-initialized.
      */
      // _GLIBCXX_RESOLVE_LIB_DEFECTS
      // 235 No specification of default ctor for reverse_iterator
      reverse_iterator() : current() { }

      /**
       *  This %iterator will move in the opposite direction that @p x does.
      */
      explicit
      reverse_iterator(iterator_type __x) : current(__x) { }

      /**
       *  The copy constructor is normal.
      */
      reverse_iterator(const reverse_iterator& __x)
      : current(__x.current) { }

      /**
       *  A %reverse_iterator across other types can be copied if the
       *  underlying %iterator can be converted to the type of @c current.
      */
      template
        reverse_iterator(const reverse_iterator<_Iter>& __x)
    : current(__x.base()) { }

      /**
       *  @return  @c current, the %iterator used for underlying work.
      */
      iterator_type
      base() const
      { return current; }

      /**
       *  @return  A reference to the value at @c --current
       *
       *  This requires that @c --current is dereferenceable.
       *
       *  @warning This implementation requires that for an iterator of the
       *           underlying iterator type, @c x, a reference obtained by
       *           @c *x remains valid after @c x has been modified or
       *           destroyed. This is a bug: http://gcc.gnu.org/PR51823
      */
      reference
      operator*() const
      {
    _Iterator __tmp = current;
    return *--__tmp;
      }

      /**
       *  @return  A pointer to the value at @c --current
       *
       *  This requires that @c --current is dereferenceable.
      */
      pointer
      operator->() const
      { return &(operator*()); }

      /**
       *  @return  @c *this
       *
       *  Decrements the underlying iterator.
      */
      reverse_iterator&
      operator++()
      {
    --current;
    return *this;
      }

      /**
       *  @return  The original value of @c *this
       *
       *  Decrements the underlying iterator.
      */
      reverse_iterator
      operator++(int)
      {
    reverse_iterator __tmp = *this;
    --current;
    return __tmp;
      }

      /**
       *  @return  @c *this
       *
       *  Increments the underlying iterator.
      */
      reverse_iterator&
      operator--()
      {
    ++current;
    return *this;
      }

      /**
       *  @return  A reverse_iterator with the previous value of @c *this
       *
       *  Increments the underlying iterator.
      */
      reverse_iterator
      operator--(int)
      {
    reverse_iterator __tmp = *this;
    ++current;
    return __tmp;
      }

      /**
       *  @return  A reverse_iterator that refers to @c current - @a __n
       *
       *  The underlying iterator must be a Random Access Iterator.
      */
      reverse_iterator
      operator+(difference_type __n) const
      { return reverse_iterator(current - __n); }

      /**
       *  @return  *this
       *
       *  Moves the underlying iterator backwards @a __n steps.
       *  The underlying iterator must be a Random Access Iterator.
      */
      reverse_iterator&
      operator+=(difference_type __n)
      {
    current -= __n;
    return *this;
      }

      /**
       *  @return  A reverse_iterator that refers to @c current - @a __n
       *
       *  The underlying iterator must be a Random Access Iterator.
      */
      reverse_iterator
      operator-(difference_type __n) const
      { return reverse_iterator(current + __n); }

      /**
       *  @return  *this
       *
       *  Moves the underlying iterator forwards @a __n steps.
       *  The underlying iterator must be a Random Access Iterator.
      */
      reverse_iterator&
      operator-=(difference_type __n)
      {
    current += __n;
    return *this;
      }

      /**
       *  @return  The value at @c current - @a __n - 1
       *
       *  The underlying iterator must be a Random Access Iterator.
      */
      reference
      operator[](difference_type __n) const
      { return *(*this + __n); }
    };
View Code

 

 我们主要以几个比较明显的表示其适配器特征的函数为例

template
class reverse_iterator
        : public iterator::iterator_category,
        typename iterator_traits<_Iterator>::value_type,
        typename iterator_traits<_Iterator>::difference_type,
        typename iterator_traits<_Iterator>::pointer,
        typename iterator_traits<_Iterator>::reference>
{
protected:
    _Iterator current;//对应的正向迭代器
    
    typedef iterator_traits<_Iterator>        __traits_type;//迭代器萃取机
    
public:
    typedef _Iterator                    iterator_type;//逆向迭代器的5中associated types 和其他迭代器相同
    typedef typename __traits_type::difference_type    difference_type;
    typedef typename __traits_type::pointer        pointer;
    typedef typename __traits_type::reference        reference;
    
    //构造函数
    reverse_iterator() : current() { }
    explicit
    reverse_iterator(iterator_type __x) : current(__x) { }
    reverse_iterator(const reverse_iterator& __x)
        : current(__x.current) { }
    
    //取出对应的正向迭代器
    iterator_type
    base() const
    { return current; }
    
    //关键点在这里, *操作取值,取对应正向迭代器的上一位
    reference
    operator*() const
    {
        _Iterator __tmp = current;
        return *--__tmp;
    }
    
    pointer
    operator->() const
    { return &(operator*()); }
    
    //前进变后退 后退变前进
    reverse_iterator&
    operator++()
    {
        --current;
        return *this;
    }
    
    reverse_iterator
    operator++(int)
    {
        reverse_iterator __tmp = *this;
        --current;
        return __tmp;
    }
    
    reverse_iterator&
    operator--()
    {
        ++current;
        return *this;
    }
    
    reverse_iterator
    operator--(int)
    {
        reverse_iterator __tmp = *this;
        ++current;
        return __tmp;
    }
    
    reverse_iterator
    operator+(difference_type __n) const
    { return reverse_iterator(current - __n); }
    
    reverse_iterator&
    operator+=(difference_type __n)
    {
        current -= __n;
        return *this;
    }
    
    reverse_iterator
    operator-(difference_type __n) const
    { return reverse_iterator(current + __n); }
    
    reverse_iterator&
    operator-=(difference_type __n)
    {
        current += __n;
        return *this;
    }
    
    reference
    operator[](difference_type __n) const
    { return *(*this + __n); }
};

 下面是反向迭代器的起点和终点函数及图解

reverse_iterator rbegin()
{
    return reverse_iterator(end());
}

reverse_iterator rend()
{
    return reverse_iterator(begin());
}

 

STL标准库-迭代器适配器_第1张图片

总结 反向迭代器,它包含其正向迭代器,使用重载其原来的operator*,operator++等操作实现其反向功能


2.insert_iterator

首先看一下算法中的copy函数源码(G2.9)

template<class InputIterator, class OutputIterator>
OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result)
{
    while (first!=last) 
    {
        *result = * first;
        ++result;
        ++first;
    }
}

 

 注意copy()函数中没有申请新的内存,采取的方式是直接赋值,那么当内存不够使用时,调用copy函数会报错

 

namespace wzj009 {

    void test_Insert_Iterator()
    {
        int myArray[] = {10,20,30,40,50,60,70};

        vector<int> v1;
        v1.resize(6);//申请内存为6

        copy(myArray, myArray + 7, v1.begin());//copy7个元素过来导致越界

        for(auto i : v1)
        {
            cout << i << endl;
        }
    }
}

 

现在我们看下面这段代码是够能够编译通过

namespace wzj010 {

    void test_Insert_Iterator()
    {
        int myArray[] = {10,20,30,40,50,60,70};

        vector<int> v1;
        v1.resize(0);

        copy(myArray, myArray + 7, inserter(v1,v1.begin()));

        for(auto i : v1)
        {
            cout << i << endl;
        }
    }
}

 STL标准库-迭代器适配器_第2张图片

 

 

我们从copy的源码中可以看得出,它的每一个方法都是写死的,那么为什么这几就能编译通过,这份功劳应该归功于运算符重载,因为insert方法会调用到insert_iterator,而insert_iterator重载了operator=,进而实现了该功能

我们看一下insert_iterator的源码

template
class insert_iterator
        : public iteratorvoid, void, void, void>
{
protected:
    _Container* container;
    typename _Container::iterator iter;
    
public:
    typedef _Container          container_type;
    
    insert_iterator(_Container& __x, typename _Container::iterator __i)
        : container(&__x), iter(__i) {}
    
    …
    insert_iterator&
    operator=(const typename _Container::value_type& __value)
    {
        iter = container->insert(iter, __value);
        ++iter;
        return *this;
    }
    
    insert_iterator&
    operator=(typename _Container::value_type&& __value)//关键点在这里,它重载了operator= 使copy函数中的 *result = * first; 调用这里的operator函数
    {
        iter = container->insert(iter, std::move(__value));
        ++iter;
        return *this;
    }
    …
}
  template
    inline insert_iterator<_Container>
    inserter(_Container& __x, _Iterator __i)
    {
      return insert_iterator<_Container>(__x,
                     typename _Container::iterator(__i));
    }//这个函数使insert调用insert_iterator

 虽然运算符重载有时使我们很难读懂代码,但其功能是非常强大的


 

3 ostream_iterator

看下面代码

namespace wzj011 {

    void test_ostream_iterator()
    {
        vector<int> v;
        for(int i = 0;i<10; i++) v.push_back(i*10);
        std::ostream_iterator<int> out_it(std::cout, "-");//将将std::cout绑定在out_it,并且输出每个元素时加以"-"
        copy(v.begin(),v.end(),out_it);
    }
}

 STL标准库-迭代器适配器_第3张图片

我紧紧是将v copy给 out_it 却输出了out_it内的元素, 那么此时我的copy功能实现了其std::cout,那么copy函数这个功能任然要归功于函数重载

 

templatechar,
         typename _Traits = char_traits<_CharT> >
class ostream_iterator
        : public iteratorvoid, void, void, void>
{
    …
    private:
        ostream_type*    _M_stream;
    const _CharT*    _M_string;
    
public:
    /// Construct from an ostream.
    ostream_iterator(ostream_type& __s) : _M_stream(&__s), _M_string(0) {}//std::ostream_iterator out_it(std::cout, “-“)将_M_stream 绑定为std::cout “-“赋值给_M_string
    
    ostream_iterator(ostream_type& __s, const _CharT* __c)
        : _M_stream(&__s), _M_string(__c)  { }
    
    /// Copy constructor.
    ostream_iterator(const ostream_iterator& __obj)
        : _M_stream(__obj._M_stream), _M_string(__obj._M_string)  { }
    
    /// Writes @a value to underlying ostream using operator<<.  If
    /// constructed with delimiter string, writes delimiter to ostream.
    ostream_iterator&
    operator=(const _Tp& __value)//
    {
        __glibcxx_requires_cond(_M_stream != 0,
                                _M_message(__gnu_debug::__msg_output_ostream)
                                ._M_iterator(*this));
        *_M_stream << __value;//将value传递给_M_stream 使其作出输出动作
        if (_M_string) *_M_stream << _M_string;
        return *this;
    }
    …
};

 

 以上的三种迭代器适配器都非常好理解,更重要的是在于我们要理解他的设计理念,运算重载功能非常强大,要好好利用

参考侯捷<>

你可能感兴趣的:(STL标准库-迭代器适配器)