一、迭代器适配器
反向迭代器
插入迭代器
IO流迭代器
其中反向迭代器可以参考以前的文章。
二、插入迭代器
插入迭代器实际上是一个输出迭代器(*it=; ++)
back_insert_iterator
back_inserter
front_insert_iterator
front_inserter
先来看示例:
<nobr>1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br> 10<br> 11<br> 12<br> 13<br> 14<br> 15<br> 16<br> 17<br> 18<br> 19<br> 20<br> 21<br> 22<br> 23<br> 24<br> 25<br> 26<br> 27<br> 28<br> 29<br> 30<br> 31<br> 32<br> 33<br> 34<br> 35<br> 36<br> 37<br> 38<br></nobr>
|
#include<iostream>
#include<vector> #include<algorithm> using namespacestd; voidShowVec( constvector< int>&v) { for(vector< int>::const_iteratorit=v.begin();it!=v.end();++it) { cout<<*it<< ''; } cout<<endl; } intmain( void) { inta[]={ 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 类的定义:
<nobr>1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br> 10<br> 11<br> 12<br> 13<br> 14<br> 15<br> 16<br> 17<br> 18<br> 19<br> 20<br> 21<br> 22<br> 23<br> 24<br> 25<br> 26<br> 27<br> 28<br> 29<br> 30<br> 31<br> 32<br> 33<br> 34<br> 35<br> 36<br> 37<br> 38<br> 39<br> 40<br> 41<br> 42<br> 43<br> 44<br> 45<br> 46<br> 47<br></nobr>
|
//TEMPLATECLASSback_insert_iterator template< class_Container> classback_insert_iterator : public_Outit { //wrappushestobackofcontainerasoutputiterator public: typedef_Containercontainer_type; typedef typename_Container::referencereference; typedef_Range_checked_iterator_tag_Checked_iterator_category; explicitback_insert_iterator(_Container&_Cont) :container(&_Cont) { //constructwithcontainer } back_insert_iterator<_Container>& operator=( typename_Container::const_reference_Val) { //pushvalueintocontainer container->push_back(_Val); return(* this); } back_insert_iterator<_Container>& operator*() { //pretendtoreturndesignatedvalue return(* this); } back_insert_iterator<_Container>& operator++() { //pretendtopreincrement return(* this); } back_insert_iterator<_Container> operator++( int) { //pretendtopostincrement return(* this); } protected: _Container*container; //pointertocontainer }; |
类内部的成员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 函数:
<nobr>1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br></nobr>
|
//TEMPLATEFUNCTIONback_inserter template< class_Container> inline back_insert_iterator<_Container>back_inserter(_Container&_Cont) { //returnaback_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 是可以使用的。
示例代码如下:
<nobr>1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br> 10<br> 11<br> 12<br> 13<br> 14<br> 15<br> 16<br> 17<br> 18<br> 19<br> 20<br> 21<br> 22<br> 23<br> 24<br> 25<br> 26<br> 27<br> 28<br> 29<br> 30<br></nobr>
|
#include<iostream>
#include<vector> #include<list> #include<algorithm> using namespacestd; voidShowList( constlist< int>&v) { for(list< int>::const_iteratorit=v.begin();it!=v.end();++it) { cout<<*it<< ''; } cout<<endl; } intmain( void) { inta[]={ 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; ->; ++; ==; !=
直接来看示例代码:
<nobr>1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br> 10<br> 11<br> 12<br> 13<br> 14<br> 15<br> 16<br> 17<br> 18<br> 19<br> 20<br></nobr>
|
#include<iostream>
#include<vector> #include<list> #include<algorithm> using namespacestd; intmain( void) { vector< int>v; //copyfromcintovector copy(istream_iterator< int>(cin),istream_iterator< int>(),back_inserter(v)); //copyfromvectortocout copy(v.begin(),v.end(),ostream_iterator< int>(cout, "")); cout<<endl; return 0; } |
首先来看istream_iterator 的源码:
<nobr>1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br> 10<br> 11<br> 12<br> 13<br> 14<br> 15<br> 16<br> 17<br> 18<br> 19<br> 20<br> 21<br> 22<br> 23<br> 24<br> 25<br> 26<br> 27<br> 28<br> 29<br> 30<br> 31<br> 32<br> 33<br> 34<br> 35<br> 36<br> 37<br> 38<br> 39<br> 40<br> 41<br> 42<br> 43<br> 44<br> 45<br> 46<br> 47<br> 48<br> 49<br> 50<br> 51<br> 52<br> 53<br> 54<br> 55<br> 56<br> 57<br> 58<br> 59<br> 60<br> 61<br> 62<br> 63<br> 64<br> 65<br> 66<br></nobr>
|
//TEMPLATECLASSistream_iterator template< class_Ty, class_Elem= char, class_Traits=char_traits<_Elem>, class_Diff=ptrdiff_t> classistream_iterator : publiciterator<input_iterator_tag,_Ty,_Diff, const_Ty*, const_Ty&> { //wrap_Tyextractsfrominputstreamasinputiterator typedefistream_iterator<_Ty,_Elem,_Traits,_Diff>_Myt; public: typedef_Elemchar_type; typedef_Traitstraits_type; typedefbasic_istream<_Elem,_Traits>istream_type; #if_SECURE_SCL typedef_Range_checked_iterator_tag_Checked_iterator_category; #endif istream_iterator() :_Myistr( 0) { //constructsingulariterator } istream_iterator(istream_type&_Istr) :_Myistr(&_Istr) { //constructwithinputstream _Getval(); } const_Ty& operator*() const { //returndesignatedvalue return(_Myval); } const_Ty* operator->() const { //returnpointertoclassobject return(&** this); } _Myt& operator++() { //preincrement _Getval(); return(* this); } protected: void_Getval() { //geta_Tyvalueifpossible if(_Myistr!= 0&&!(*_Myistr>>_Myval)) _Myistr= 0; } istream_type*_Myistr; //pointertoinputstream _Ty_Myval; //lookaheadvalue(validif_Myistrisnotnull) }; |
上面只截取了部分用上的源码,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 是否相等,其实
operator != 里面是判断它们的成员指针_Myistr 是否相等,在_Getval 函数可以看到,当我们输入错误(类型不匹配)或者ctrl+z,
则istream_iterator<int>(cin) 的_Myistr 被置为0,此时本来istream_iterator<int>() 的_Myistr 就为0,故相等,不再继续执行下去。
如果不等,即输入正确的话,*First 调用istream_iterator 类的operator* 直接返回_Myval ,接着调用back_insert_iterator 类的
operator=,即调用container 的push_back ,将_Myval 压入容器。++_Dest 是没什么效果的,而++_First 在istream_iterator 类的
operator++ 中会继续调用_Getval,即继续获得键盘输入覆盖_Myval。
再来看ostream_iterator 的源码:
<nobr>1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br> 10<br> 11<br> 12<br> 13<br> 14<br> 15<br> 16<br> 17<br> 18<br> 19<br> 20<br> 21<br> 22<br> 23<br> 24<br> 25<br> 26<br> 27<br> 28<br> 29<br> 30<br> 31<br> 32<br> 33<br> 34<br> 35<br> 36<br> 37<br> 38<br> 39<br> 40<br> 41<br> 42<br> 43<br> 44<br> 45<br> 46<br></nobr>
|
//TEMPLATECLASSostream_iterator template< class_Ty, class_Elem= char, class_Traits=char_traits<_Elem>> classostream_iterator : public_Outit { //wrap_Tyinsertstooutputstreamasoutputiterator public: typedef_Elemchar_type; typedef_Traitstraits_type; typedefbasic_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) { //constructfromoutputstreamanddelimiter } ostream_iterator<_Ty,_Elem,_Traits>& operator=( const_Ty&_Val) { //insertvalueintooutputstream,followedbydelimiter *_Myostr<<_Val; if(_Mydelim!= 0) *_Myostr<<_Mydelim; return(* this); } ostream_iterator<_Ty,_Elem,_Traits>& operator*() { //pretendtoreturndesignatedvalue return(* this); } ostream_iterator<_Ty,_Elem,_Traits>& operator++() { //pretendtopreincrement return(* this); } protected: const_Elem*_Mydelim; //pointertodelimiterstring(NB:notfreed) ostream_type*_Myostr; //pointertooutputstream }; |
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++编程规范