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; } 
posted @ 2019-11-30 22:44  技术狂人djc  阅读(329)  评论(0编辑  收藏  举报