一、迭代器适配器

反向迭代器

插入迭代器

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[] = {1, 2, 3, 4, 5};
    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->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[] = {1, 2, 3, 4, 5};
    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;
}

 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 是否相等,其实

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

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

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
 
// 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++编程规范

迭代器适配器{(插入迭代器back_insert_iterator)、IO流迭代器(istream_iterator、ostream_iterator)}的更多相关文章

  1. 第十五篇:流迭代器 + 算法灵活控制IO流

    前言 标准算法配合迭代器使用太美妙了,使我们对容器(数据)的处理更加得心应手.那么,能不能对IO流也使用标准算法呢?有人认为不能,他们说因为IO流不是容器,没有迭代器,故无法使用标准算法.他们错了,错 ...

  2. 流迭代器 + 算法灵活控制IO流

    前言 标准算法配合迭代器使用太美妙了,使我们对容器(数据)的处理更加得心应手.那么,能不能对IO流也使用标准算法呢?有人认为不能,他们说因为IO流不是容器,没有迭代器,故无法使用标准算法.他们错了,错 ...

  3. C++STL:流迭代器

    流迭代器是一种迭代器适配器.istream_iterator用于读取输入流,ostream_iterator用于写输出流.这些迭代器将它们所对应的流视为特定类型的元素序列.使用流迭代器时,可以用泛型算 ...

  4. 【C++ STL应用与实现】18: 怎样使用迭代器适配器

    本系列文章的文件夹在这里:文件夹. 通过文件夹里能够对STL整体有个大概了解 前言 本文介绍了STL中的迭代器适配器(iterator adapter)的概念及其用法演示样例.迭代器适配器能够和标准库 ...

  5. STL 迭代器适配器(iterator adapter)

    iterator adapter graph LR iterator --- reverse_iterator iterator --- Insert_iterator iterator --- io ...

  6. function adapter(函数适配器)和迭代器适配器

    所谓function adapter(函数适配器)是指能够将不同的函数对象(或是和某值或某寻常函数)结合起来的东西,它自身也是个函数对象. 迭代器适配器  运用STL中的迭代器适配器,可以使得算法能够 ...

  7. 迭代器适配器(一)back_inserter和front_inserter的实现

    本文讨论back_inserter和front_inserter的实现. 当我们调用copy函数的时候,要确保目标容器具有足够大的空间,例如: //将other的所有元素拷贝到以coll.begin( ...

  8. STL标准库-迭代器适配器

    技术在于交流.沟通,本文为博主原创文章转载请注明出处并保持作品的完整性 这次主要介绍一下迭代器适配器.以reverse_iterator(反向迭代器),insert_iterator(插入迭代器),o ...

  9. list的迭代器能解决并发问题,collection 的迭代器不能解决并发问题,for可以解决并发问题

    list的迭代器能解决并发问题,collection 的迭代器不能解决并发问题 为什么list支持add,collection不支持 例如有两个人同时添加第三个元素 list的迭代器能锁定线程 只有等 ...

随机推荐

  1. Circuit provides reference for multiple ADCs

    The achievable accuracy for systems with multiple ADCs depends directly on the reference voltages ap ...

  2. What is the fastest way of (not) logging?

    原文地址:http://www.slf4j.org/faq.html#logging_performance SLF4J supports an advanced feature called par ...

  3. ORACLE单表理论最大记录数

    不考虑硬件诸如内存,存储等硬件的限制. 一张表理论能存储多少条记录呢? 假设: 一个tablespace中包含1022个datafiles, 单个datafiles的最大是32G 假设每个block是 ...

  4. Code First 数据库的表中属性的配置

      数据类型的约定配置 默认规则 列的数据类型是由数据库决定的,SqlServer的默认规则如下 String: nvarchar(MAX) Int:int Bool:bit Decimal:deci ...

  5. [译林军] 译~CrossBridge 简介

    本文由 9ria 社区译林军翻译,转载请注明出处.加入译林军 :http://bbs.9ria.com/thread-286920-1-1.html CrossBridge 是  Adobe  Fla ...

  6. git hub的GUI软件配置与使用

    1. 安装两个软件 1. git的命令行程序--git for windows:http://git-scm.com/download/win 2. git的GUI程序--tortoisegit:ht ...

  7. SWT常用组件

    SWT类所代表的事件常量: 事件类型常量 说明 SWT.Activate 当激活窗口时 SWT.Arm 菜单项被选中之前 SWT.Close 关闭窗口时 SWT.Collapse 折叠树的节点时 SW ...

  8. 解决kylin build cube第一步报错:java.lang.NullPointerException

    报错栈: -- ::, ERROR [pool--thread-] threadpool.DefaultScheduler: : ExecuteException job:933bc47a-302c- ...

  9. 关于LightMapping和NavMesh烘焙的动态载入

    熟悉unity的朋友都应该知道,unity有内部LightMapping烘焙和NavMesh寻路的功能.但这些非常好用的功能,都是基于对某个已经保存的关卡(scene)进行烘焙(Bake)的操作,我一 ...

  10. Linux进程间通信—信号量

    二.信号量(semophore) 信号量是一种计数器,可以控制进程间多个线程或者多个进程对资源的同步访问,它常实现为一种锁机制.实质上,信号量是一个被保护的变量,并且只能通过初始化和两个标准的原子操作 ...