从零开始学C++之STL(十):迭代器适配器{(插入迭代器back_insert_iterator)、IO流迭代器(istream_iterator、ostream_iterator)}

转:http://blog.csdn.net/jnu_simba/article/details/9532259

一、迭代器适配器

反向迭代器

插入迭代器

IO流迭代器


其中反向迭代器可以参考以前的文章


二、插入迭代器

插入迭代器实际上是一个输出迭代器(*it=; ++)


back_insert_iterator
back_inserter


front_insert_iterator
front_inserter


先来看示例:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>
#include <vector>
#include <algorithm>

using  namespace std;

void ShowVec( const vector< int> &v)
{
     for (vector< int>::const_iterator it = v.begin(); it != v.end(); ++it)
    {
        cout << *it <<  ' ';
    }
    cout << endl;
}
int main( void)
{
     int a[] = { 12345};
    vector< int> v(a, a +  5);
    vector< int> v2;

    back_insert_iterator<vector< int> > bii(v);
     //*bii = 6;
    bii =  6;
    ShowVec(v);

    back_insert_iterator<vector< int> > bii2(v2);
    copy(v.begin(), v.end(), bii2);
    ShowVec(v2);

    back_inserter(v) =  7;
    ShowVec(v);

    copy(v.begin(), v.end(), back_inserter(v2));
    ShowVec(v2);


     return  0;
}

查看back_insert_iterator 类的定义:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// TEMPLATE CLASS back_insert_iterator
template< class _Container>
class back_insert_iterator
    :  public _Outit
{
     // wrap pushes to back of container as output iterator
public:
     typedef _Container container_type;
     typedef  typename _Container::reference reference;

     typedef _Range_checked_iterator_tag _Checked_iterator_category;

     explicit back_insert_iterator(_Container &_Cont)
        : container(&_Cont)
    {
         // construct with container
    }

    back_insert_iterator<_Container> & operator=(
         typename _Container::const_reference _Val)
    {
         // push value into container
        container->push_back(_Val);
         return (* this);
    }

    back_insert_iterator<_Container> & operator*()
    {
         // pretend to return designated value
         return (* this);
    }

    back_insert_iterator<_Container> & operator++()
    {
         // pretend to preincrement
         return (* this);
    }

    back_insert_iterator<_Container>  operator++( int)
    {
         // pretend to postincrement
         return (* this);
    }

protected:
    _Container *container;   // pointer to container
};

类内部的成员container 保存的是指向容器的指针,重载了*, ++, = 等运算符,* 和 ++ 返回的都是迭代器本身,主要看 赋值运算符:


container->push_back(_Val); 即调用了容器的push_back 函数, 所以可以直接写 bii = 6; 即将6压入容器末尾。程序中还调用了copy 


函数,回顾copy 源码,主要是以下代码:


for (; _First != _Last; ++_Dest, ++_First)



        *_Dest = *_First;


其中,_First 和 _Last 分别是v.begin() 和 v.end(), _Dest 是 bii2,上面也说了,*_Dest 返回的是自身,而且++_Dest 返回的也是自


身,从_First 遍历到 _Last ,调用back_insert_iterator 类的operator=,即不断地执行container->push_back(_Val); 容器的元素位置会


自动移动。


再来看back_inserter 函数:

 C++ Code 
1
2
3
4
5
6
7
// TEMPLATE FUNCTION back_inserter
template< class _Container>  inline
back_insert_iterator<_Container> back_inserter(_Container &_Cont)
{
     // return a back_insert_iterator
     return (std::back_insert_iterator<_Container>(_Cont));
}

实际上返回的也是一个back_insert_iterator 对象,所以能直接替换掉bii2。


当然了,与back 配对的就是front,back 是末尾插入,front 是头端插入,需要注意的是front_insert_iterator 的operator= 调用了


push_front 函数,故如vector 是没有实现push_front 的,不能使用front_insert_iterator ,而list 和 deque 是可以使用的。


示例代码如下:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
#include <vector>
#include <list>
#include <algorithm>

using  namespace std;

void ShowList( const list< int> &v)
{
     for (list< int>::const_iterator it = v.begin(); it != v.end(); ++it)
    {
        cout << *it <<  ' ';
    }
    cout << endl;
}

int main( void)
{
     int a[] = { 12345};
    list< int> l(a, a +  5);
    list< int> ll;

    front_insert_iterator<list< int> > fii(l);
    fii =  0;
    ShowList(l);

    copy(l.begin(), l.end(), front_inserter(ll));
    ShowList(ll);
     return  0;
}


三、IO流迭代器


输出流迭代器(ostream_iterator)


*it=; ++


输入流迭代器(istream_iterator)

=*it; ->; ++; ==; !=


直接来看示例代码:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <vector>
#include <list>
#include <algorithm>

using  namespace std;

int main( void)
{
    vector< int> v;

     // copy from cin to vector
    copy(istream_iterator< int>(cin), istream_iterator< int>(), back_inserter(v));

     // copy from vector to cout
    copy(v.begin(), v.end(), ostream_iterator< int>(cout,  " "));
    cout << endl;

     return  0;
}

首先来看istream_iterator 的源码:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// TEMPLATE CLASS istream_iterator
template <  class _Ty,
          class _Elem =  char,
          class _Traits = char_traits<_Elem>,
          class _Diff = ptrdiff_t >
class istream_iterator
    :  public iterator < input_iterator_tag, _Ty, _Diff,
       const _Ty *,  const _Ty & >
{
     // wrap _Ty extracts from input stream as input iterator
     typedef istream_iterator<_Ty, _Elem, _Traits, _Diff> _Myt;
public:
     typedef _Elem char_type;
     typedef _Traits traits_type;
     typedef basic_istream<_Elem, _Traits> istream_type;

#if _SECURE_SCL
     typedef _Range_checked_iterator_tag _Checked_iterator_category;
#endif

    istream_iterator()
        : _Myistr( 0)
    {
         // construct singular iterator
    }

    istream_iterator(istream_type &_Istr)
        : _Myistr(&_Istr)
    {
         // construct with input stream
        _Getval();
    }

     const _Ty & operator*()  const
    {
         // return designated value

         return (_Myval);
    }

     const _Ty * operator->()  const
    {
         // return pointer to class object
         return (& ** this);
    }

    _Myt & operator++()
    {
         // preincrement

        _Getval();
         return (* this);
    }


protected:
     void _Getval()
    {
         // get a _Ty value if possible
         if (_Myistr !=  0 && !(*_Myistr >> _Myval))
            _Myistr =  0;
    }

    istream_type *_Myistr;   // pointer to input stream
    _Ty _Myval;  // lookahead value (valid if _Myistr is not null)
};

上面只截取了部分用上的源码,istream_iterator 类有两个成员,一个是输入流对象指针,一个是输入的值,如


 istream_iterator<int>(cin)  调用构造函数,初始化_Myistr,且通过函数_Getval() 初始化_Myval,_Getval() 调用输入流的


operator>> 将键盘输入的值赋予_Myval。而 istream_iterator<int>() 呢初始化_Myistr 为0,此时_Myval 被忽略。


回顾copy 源码,主要是以下代码:


for (; _First != _Last; ++_Dest, ++_First)



        *_Dest = *_First;


此时_First 和 _Last 是 istream_iterator<int> 类型,_Dest是back_insert_iterator 类型,而判断_First 和 _Last 是否相等,其实


operator != 里面是判断它们的成员指针_Myistr 是否相等,在_Getval 函数可以看到,当我们输入错误(类型不匹配)或者ctrl+z,


则 istream_iterator<int>(cin) 的_Myistr 被置为0,此时本来 istream_iterator<int>() 的_Myistr 就为0,故相等,不再继续执行下去。


如果不等,即输入正确的话,*First 调用istream_iterator 类的operator* 直接返回_Myval ,接着调用back_insert_iterator 类的


operator=,即调用container 的push_back ,将_Myval 压入容器。++_Dest 是没什么效果的,而++_First 在istream_iterator 类的


operator++ 中会继续调用_Getval,即继续获得键盘输入覆盖_Myval。


再来看ostream_iterator 的源码:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// TEMPLATE CLASS ostream_iterator
template< class _Ty,
     class _Elem =  char,
     class _Traits = char_traits<_Elem> >
     class ostream_iterator
        :  public _Outit
    {    // wrap _Ty inserts to output stream as output iterator
public:
     typedef _Elem char_type;
     typedef _Traits traits_type;
     typedef basic_ostream<_Elem, _Traits> ostream_type;

#if _SECURE_SCL
     typedef _Range_checked_iterator_tag _Checked_iterator_category;
#endif

    ostream_iterator(ostream_type& _Ostr,
         const _Elem *_Delim =  0)
        : _Myostr(&_Ostr), _Mydelim(_Delim)
        {    // construct from output stream and delimiter
        }

    ostream_iterator<_Ty, _Elem, _Traits>&  operator=( const _Ty& _Val)
        {    // insert value into output stream, followed by delimiter
        *_Myostr << _Val;
         if (_Mydelim !=  0)
            *_Myostr << _Mydelim;

         return (* this);
        }

    ostream_iterator<_Ty, _Elem, _Traits>&  operator*()
        {    // pretend to return designated value
         return (* this);
        }

    ostream_iterator<_Ty, _Elem, _Traits>&  operator++()
        {    // pretend to preincrement
         return (* this);
        }

protected:

     const _Elem *_Mydelim;   // pointer to delimiter string (NB: not freed)
    ostream_type *_Myostr;   // pointer to output stream
    };

ostream_iterator 类也有两个成员,一个是输出流对象指针,一个是字符串指针,看上面的copy 代码,此时_First 和 _Last 


分别是v.begin() 和 v.end(),_Dest是 ostream_iterator<int> 类型,*_Dest 返回自身,++_Dest 也返回自身,而在operator= 函数中


*_Myostr << _Val;


if (_Mydelim != 0)


*_Myostr << _Mydelim;


即判断如果还有传入字符串,则在输出元素值之后,还伴随着字符串的输出。所以示例代码中的输出是伴随着空格的。


参考:

C++ primer 第四版
Effective C++ 3rd
C++编程规范


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值