• STL标准库-迭代器适配器


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

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

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

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


    1.reverse_iterator反向迭代器的实现

    下面是reverse_iterator的源码

    template<typename _Iterator>
        class reverse_iterator
        : public iterator<typename iterator_traits<_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<typename _Iter>
            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<typename _Iterator>
    class reverse_iterator
            : public iterator<typename iterator_traits<_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());
    }

    总结 反向迭代器,它包含其正向迭代器,使用重载其原来的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;
            }
        }
    }

     

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

    我们看一下insert_iterator的源码

    template<typename _Container>
    class insert_iterator
            : public iterator<output_iterator_tag, void, 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<typename _Container, typename _Iterator>
        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);
        }
    }

     

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

    template<typename _Tp, typename _CharT = char,
             typename _Traits = char_traits<_CharT> >
    class ostream_iterator
            : public iterator<output_iterator_tag, void, 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<int> 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源码剖析>>

  • 相关阅读:
    0621S02E03
    欢迎C#/ASP.NET/MS SQL Server开发Web程序的朋友加入Edrp开发组
    “浪漫满屋”看后感
    欢迎C#/ASP.NET/MS SQL Server开发Web程序的朋友加入Edrp开发组
    “浪漫满屋”看后感
    类型或命名空间名称“UI”在类或命名空间“System.Web”中不存在(是否缺少程序集引用?)的解决方法
    类型或命名空间名称“UI”在类或命名空间“System.Web”中不存在(是否缺少程序集引用?)的解决方法
    伤筋动骨100天吗?
    欢迎Edrp开发组第一个成员Zhuang Liu的加入!
    欢迎Edrp开发组第一个成员Zhuang Liu的加入!
  • 原文地址:https://www.cnblogs.com/LearningTheLoad/p/7639042.html
Copyright © 2020-2023  润新知