• 迭代器适配器{(插入迭代器back_insert_iterator)、IO流迭代器(istream_iterator、ostream_iterator)}


    一、迭代器适配器

    反向迭代器

    插入迭代器

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

  • 相关阅读:
    软件测试(理论基础)
    Android NDK常见配置问题的解决方案
    Eclemma各种安装方式以及安装失败解决
    检测Buffer Overflow的几种方法
    转: 跟我一起写 Makefile
    流敏感、路径敏感、上下文敏感
    Symbolic Exectuion with Mixed ConcreteSymbolic Solving
    基于ajc的代码编织
    第一次个人编程作业
    第一次博客作业
  • 原文地址:https://www.cnblogs.com/alantu2018/p/8471465.html
Copyright © 2020-2023  润新知