一、迭代器适配器

反向迭代器

插入迭代器

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. Windows蓝屏dump文件查看器(转)

    Windbg-分析Windows蓝屏原因利器[转]下载地址先声明下,虽然用windbg诊断蓝屏之前网络上已经有人发过教程了,但就我而言, 学会使用windbg来诊断蓝屏也算是自己的原创吧.以前看一个微 ...

  2. C# http Get/POST请求封装类

    C#HttpHelper官方产品发布与源码下载---苏飞版 http://www.sufeinet.com/thread-3-1-1.html 在C#用HttpWebRequest中发送GET/HTT ...

  3. JavaScript面向对象编程指南(第2版)》读书笔记

    一.对象 1.1 获取属性值的方式 water = { down: false } console.log(water.down) // false console.log(water['down'] ...

  4. javascript基础编程の变量、对象、数据类型及函数

    在web标准中.网页由结构.表现形式和行为三个部分组成. 结构标准---->XHTML: 表现形式标准----->CSS: 行为标准----->javascript: javascr ...

  5. Android中各级目录的作用

    Android中各级目录的作用 一.目录结构  src目录---存放源代码文件   gen目录---ADT插件生成的文件,(自动生成) R.java文件  drawable类---给图片生产的ID  ...

  6. Latex作者单位的写法—AND 首页脚注

    IEEE会议的模板 以四个作者为例 正常: 作者单位如果名字较短,可以直接写在作者对应的下面,邮箱可以对应写在再接下来的下面. 一 如果邮箱较长,可以用\thanks{ }命令将其变为脚注.例如: ~ ...

  7. 对 getaddrinfo Android 返回错误 EAI_BADFLAGS

    我们尝试使用 getaddrinfo 对 Android API 14 及以上 (在 c + + 代码使用 NDK r12) 从 IPV4 获得合成的 IPV6 地址 address .这是在 IPV ...

  8. 采用web service传输超大数据

    因为以前也没有做过相关的web service开发,对于Xfire也只是知道有这么一个框架.当然现在它已经变成apache基金会旗下的一个开源项目CXF.不过,现在依旧有很多公司还在用Xfire作we ...

  9. vmware workstation无法打开内核设备问题处理办法

    vmware workstation无法打开内核设备:\\Global\\vmx86 ? 解决办法如下: 开始 - 运行(输入CMD)- 确定或者回车,打开管理员命令窗口: net start vmc ...

  10. SQL Server之RAID简介

    一: RAID简介 RAID(Redundant Array of Independent Disk 独立冗余磁盘阵列)是一项数据保护策略. 二: RAID的几种常用级别 1. RAID 0: 通过并 ...