迭代器適配器{(插入迭代器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++編程規范


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM