一、迭代器適配器
反向迭代器
插入迭代器
IO流迭代器
其中反向迭代器可以參考以前的文章。
二、插入迭代器
插入迭代器實際上是一個輸出迭代器(*it=; ++)
back_insert_iterator
back_inserter
front_insert_iterator
front_inserter
先來看示例:
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 類的定義:
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 ,調用back_insert_iterator 類的operator=,即不斷地執行container->push_back(_Val); 容器的元素位置會
自動移動。
再來看back_inserter 函數:
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 是可以使用的。
示例代碼如下:
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; ->; ++; ==; !=
直接來看示例代碼:
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; } |
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 類的
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++編程規范