• STL 迭代器适配器(iterator adapter)


    iterator adapter

    graph LR iterator --- reverse_iterator iterator --- Insert_iterator iterator --- iostream_iterator Insert_iterator --- back_insert_iterator Insert_iterator --- front_insert_iterator Insert_iterator --- insert_iterator

    插入迭代器:将一般迭代器的赋值操作转变为插入操作。

    insert iterator

    当用户对inserter iterator作赋值操作时,就在inserter iterator类中定义的operator()中调用底层容器的插入操作(push_back,push_front,insert,etc.).

    以back_inserter插入迭代适配器为例:(front_inserter和inserter与该类相类似)

    template <class _Container>
    inline back_insert_iterator<_Container> back_inserter(_Container& __x) {
      return back_insert_iterator<_Container>(__x);
    }
    

    当用户调用back_inserter函数时,函数实际返回后向插入迭代器类(back_insert_iterator)对象,并将容器参数传递给后向插入迭代器类的构造函数。
    后向插入迭代器类代码(back_insert_iterator):

    template <class _Container>
    class back_insert_iterator {
    protected:
      _Container* container;
    public:
      typedef _Container          container_type;
      typedef output_iterator_tag iterator_category;
      typedef void                value_type;
      typedef void                difference_type;
      typedef void                pointer;
      typedef void                reference;
    
      explicit back_insert_iterator(_Container& __x) : container(&__x) {}
      back_insert_iterator<_Container>&
      operator=(const typename _Container::value_type& __value) { 
        container->push_back(__value);
        return *this;
      }
      back_insert_iterator<_Container>& operator*() { return *this; }
      back_insert_iterator<_Container>& operator++() { return *this; }
      back_insert_iterator<_Container>& operator++(int) { return *this; }
    };
    

    类中有容器类指针_Container* container,指向待插入的容器。在类中定义的赋值操作符=中,调用了底层容器的push_back函数,将operator=参数__value插入到容器尾部。

    类中还重载了迭代器操作符:dereference [],prefix_increment[++],post_increment[++(int)]。在其函数体中只是简单地返回当前迭代器本身(this),并未进行相应的前进等操作,说明对此类back_insert_iterator对象进行上述操作是不会产生什么效果。

    结合例子分析:

    #include<iostream>
    #include<vector>
    #include<algorithm>
    #include<iterator>
    
    using namespace std;
    
    int main(){
    	int ia[]={1,5,3,6,4,8,9};
    	vector<int> ivec(ia,ia+7);
    	ostream_iterator<int> outite(cout," ");
    
    	copy(ia,ia+3,back_inserter(ivec));        //a
    	copy(ivec.begin(),ivec.end(),outite);
            //1 5 3 6 4 8 9 1 5 3
    	cout<<endl;
    
    	return 0;
    }
    

     程序中a行调用back_inserter函数,生成对ivec向量的后向迭代器对象(back_insert_iterator object),并将该对象传入到copy算法。在copy算法中将利用该对象作为函数,对容器中的对象进行处理。
     在程序中,后向迭代器对象只是被当作一个函数(functor)使用,对容器调用该对象提供的功能,而不是像传统的迭代器来访问数组中的元素,因此,对其进行dereference [*],prefix_increment[++],post_increment[++(int)]操作都不会产生什么效果。

    程序的运行结果为:
    1 5 3 6 4 8 9 1 5 3

    reverse iterator

    反向迭代器:将迭代器的移动方向倒转:前进变为后退,后退变为前进。

    在某些容器类中定义反向迭代器成员,如vector:

    template <class _Tp, class _Alloc = __STL_DEFAULT_ALLOCATOR(_Tp) >
    class vector : protected _Vector_base<_Tp, _Alloc> 
    {
        //...
        typedef value_type* iterator;   // vector的迭代器是普通指针
        typedef const value_type* const_iterator;
        typedef reverse_iterator<const_iterator> const_reverse_iterator;
        typedef reverse_iterator<iterator> reverse_iterator;
    
        reverse_iterator rbegin()
        { return reverse_iterator(end()); }
        const_reverse_iterator rbegin() const
        { return const_reverse_iterator(end()); }
        reverse_iterator rend()
        { return reverse_iterator(begin()); }
        const_reverse_iterator rend() const
        { return const_reverse_iterator(begin()); }
        //...
    }
    

    在上面的代码中,该类还定义了rbegin(),rend()等函数,可以返回容器的反向迭代器。

    reverse_iterator类的定义如下:

    template <class _RandomAccessIterator, class _Tp, class _Reference = _Tp&,
              class _Distance = ptrdiff_t> 
    class reverse_iterator {
      typedef reverse_iterator<_RandomAccessIterator, _Tp, _Reference, _Distance>
            _Self;
    protected:
      _RandomAccessIterator current;
    public:
      typedef random_access_iterator_tag iterator_category;
      typedef _Tp                        value_type;
      typedef _Distance                  difference_type;
      typedef _Tp*                       pointer;
      typedef _Reference                 reference;
    
      reverse_iterator() {}
      explicit reverse_iterator(_RandomAccessIterator __x) : current(__x) {}
      _RandomAccessIterator base() const { return current; }
      _Reference operator*() const { return *(current - 1); }
    #ifndef __SGI_STL_NO_ARROW_OPERATOR
      pointer operator->() const { return &(operator*()); }
    #endif /* __SGI_STL_NO_ARROW_OPERATOR */
      _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;
      }
      _Self operator+(_Distance __n) const {
        return _Self(current - __n);
      }
      _Self& operator+=(_Distance __n) {
        current -= __n;
        return *this;
      }
      _Self operator-(_Distance __n) const {
        return _Self(current + __n);
      }
      _Self& operator-=(_Distance __n) {
        current += __n;
        return *this;
      }
      _Reference operator[](_Distance __n) const { return *(*this + __n); }
    };
    

    迭代器的前进,后退等操作都与普通迭代器的方向相反。

      _Reference operator*() const { return *(current - 1); }
    

    在解引用函数*定义中,函数先向前进一步,然后再对其解引用并返回,而正向迭代器则是直接解析其指向的元素。

    stream iterator

    流迭代器:将迭代器绑定到一个数据流(stream)对象上。包括istream_iterator和ostream_iterator。

    graph LR stream_iterator --- istream_iterator stream_iterator --- ostream_iterator istream_iterator -.-> istream ostream_iterator -.-> ostream

    ostream_iterator

    istream iterator在类的内部有一个istream类型的指针。当用户对迭代器进行操作时,迭代器内部通过该指针指向的输入流对象,完成相应的操作。

    template <class _Tp, class _Dist>
    class istream_iterator {
      template <class _T1, class _D1>
      friend bool operator==(const istream_iterator<_T1, _D1>&,
                             const istream_iterator<_T1, _D1>&);
    protected:
      istream* _M_stream;
      _Tp _M_value;
      bool _M_end_marker;
      void _M_read() {
        _M_end_marker = (*_M_stream) ? true : false;
        if (_M_end_marker) *_M_stream >> _M_value;
        _M_end_marker = (*_M_stream) ? true : false;
      }
    public:
      typedef input_iterator_tag  iterator_category;
      typedef _Tp                 value_type;
      typedef _Dist               difference_type;
      typedef const _Tp*          pointer;
      typedef const _Tp&          reference;
    
      istream_iterator() : _M_stream(&cin), _M_end_marker(false) {}
      istream_iterator(istream& __s) : _M_stream(&__s) { _M_read(); }
      reference operator*() const { return _M_value; }
      pointer operator->() const { return &(operator*()); }
      istream_iterator<_Tp, _Dist>& operator++() { 
        _M_read(); 
        return *this;
      }
      istream_iterator<_Tp, _Dist> operator++(int)  {
        istream_iterator<_Tp, _Dist> __tmp = *this;
        _M_read();
        return __tmp;
      }
    };
    

    类中istream类指针_M_stream实现迭代器的数据输入操作。_M_value变量保存最近输入的值。该类的默认构造函数用cin初始化_M_stream成员,并设置流输入结束符。用户也可以自己指定其他输入流(如文件流等)来初始化输入流指针成员_M_stream。

    istream_iterator对象通常配合算法使用,可以用输入流完成对容器的初始化或赋值等功能。在算法中会调用istream_iterator对象的前进操作符号,而在自增操作符函数体中,调用了_M_read函数,在_M_read函数中,先判断是否到达流结尾,若未到达结尾,则调用输入流的operator>> ,将输入值赋给_M_value,并更新到达结尾状态。解引用操作符则可返回当前的最新输入值_M_value。每次对istream_iterator对象调用operator++,都会引发数据输入,并将输入值保存在缓存变量中。

    ostream_iterator

    ostream_iterator 类完成数据的输出操作。于istream_iterator的差别主要在赋值操作符operator=中:

      ostream_iterator<_Tp>& operator=(const _Tp& __value) { 
        *_M_stream << __value;
        if (_M_string) *_M_stream << _M_string;
        return *this;
      }
    

    每次对ostream_iterator类对象调用赋值操作时,都会将右操作数 __value输出到指定的输出流中,并输入指定的分割字符串。

    ostream_iterator类中封锁了其他几个操作符的功能,使得对其进行操作失效:

      ostream_iterator<_Tp>& operator*() { return *this; }
      ostream_iterator<_Tp>& operator++() { return *this; } 
      ostream_iterator<_Tp>& operator++(int) { return *this; } 
    
  • 相关阅读:
    Codeforces Round #363 (Div. 2)
    Codeforces Round #312 (Div. 2)
    Codeforces Round #354 (Div. 2)
    Codeforces Round #353 (Div. 2) A
    Codeforces Round #347 (Div. 2) B
    Codeforces Round #326 (Div. 2)
    Spring中数据库技术--获得DataSource
    查询练习
    查询语句
    Oracle数据库的使用
  • 原文地址:https://www.cnblogs.com/SupremeGIS-Developer/p/11964352.html
Copyright © 2020-2023  润新知