在STL中,迭代器主要分为5大类:Input Iterator, Output Iterator, Forward Iterator, Bidirectional Iterator和RandomAccess Iterator。
关系如下:
其中每一个左边的迭代器都实现了右边迭代器的方法。左边迭代器是对右边迭代器的进一步强化。
In this graph, each iterator category implements the functionalities of all categories to its right:
(1) Input and output iterators are the most limited types of iterators, specialized in performing only sequential input or output operations.
(2) Forward iterators have all the functionality of input and output iterators, although they are limited to one direction in which to iterate through a range.
(3) Bidirectional iterators can be iterated through in both directions. All standard containers support at least bidirectional iterators types.
(4) Random access iterators implement all the functionalities of bidirectional iterators, plus, they have the ability to access ranges non-sequentially: offsets can be directly applied to these iterators without iterating through all the elements in between. This provides these iterators with the same functionality as standard pointers (pointers are iterators of this category).
下面的一个表格描述了各个迭代器所具有的操作:
下面介绍STL中所提供的与迭代器相关的操作。
1. 迭代器基础:iterator和iterator_traits
(1). iterator类
STL定义了一个迭代器的基类iterator
定义如下:
template <class Category, class T, class Distance = ptrdiff_t,
class Pointer = T*, class Reference = T&>
struct iterator {
typedef T value_type;
typedef Distance difference_type;
typedef Pointer pointer;
typedef Reference reference;
typedef Category iterator_category;
};
主要定义了迭代器所要使用的内部类型:
value_type: 代表迭代器所指对象的类型。
difference_type:代表两个迭代器之间的距离
reference_type:代表迭代器所指对象的引用类型。简言之,它是operator*()的返回类型
pointer_type:代表迭代器所致对象的指针类型。简言之,它是operator->()的返回类型
iterator_category:代表1中提出的五种迭代器的类型标识
Category的值就是之间介绍的五类迭代器类型,即下表:
下面是一个实现迭代器的例子,从iterator类继承,实现了输入迭代器的功能:
#include <iostream>
#include <iterator>
using namespace std;
class myiterator: public iterator<input_iterator_tag,int>
{
int *p;
public:
myiterator(int *x):p(x){}
myiterator(const myiterator& mit):p(mit.p){}
myiterator& operator++(){++p;return *this;}
myiterator operator++(int){
myiterator tmp(*this);
operator++();
return tmp;
}
bool operator==(const myiterator& rhs){
return p==rhs.p;
}
bool operator!=(const myiterator& rhs){
return p!=rhs.p;
}
int& operator*(){
return *p;
}
};
int main(){
int numbers[]={10,20,30,40,50};
int sz=sizeof(numbers)/sizeof(numbers[0]);
myiterator be(numbers);
myiterator ed(numbers+sz);
for(myiterator it=be;it!=ed;++it)
cout<<*it<<' ';
cout<<endl;
}
(2). iterator_traits类模板
主要用于迭代器内部类型的获取。
iterator_traits为屏蔽了下层各容器类型的不同,为上层的应用(主要是一些算法,如advance()等)提供了统一的用户界面。
定义如下:
template <class Iterator> struct iterator_traits {
typedef typename Iterator::difference_type difference_type;
typedef typename Iterator::value_type value_type;
typedef typename Iterator::pointer pointer;
typedef typename Iterator::reference reference;
typedef typename Iterator::iterator_category iterator_category;
}
两个模板特化:
template <class T> struct iterator_traits<T*> {
typedef ptrdiff_t difference_type;
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef random_access_iterator_tag iterator_category;
}
template <class T> struct iterator_traits<const T*> {
typedef ptrdiff_t difference_type;
typedef T value_type;
typedef const T* pointer;
typedef const T& reference;
typedef random_access_iterator_tag iterator_category;
}
如下图:
下图是advance函数的调用关系:
2. 迭代器操作函数
(1)advace操作:
前移迭代器
原型:
template <class InputIterator, class Distance>
void advance (InputIterator& i, Distance n);
(2)distance操作:
求两个迭代器之间的距离
原型:
template<class InputIterator>
typename iterator_traits<InputIterator>::difference_type
distance (InputIterator first, InputIterator last);
(3)back_inserter
为容器返回一个反向插入迭代器。
原型:
template <class Container>
back_insert_iterator<Container> back_inserter (Container& x);
反向插入迭代器是一种特殊的输出迭代器,它在容器的结尾进行插入操作。
如下面的例子:
#include <iostream>
#include <iterator>
#include <vector>
using namespace std;
int main () {
vector<int> firstvector, secondvector;
for (int i=1; i<=5; i++)
{ firstvector.push_back(i); secondvector.push_back(i*10); }
copy (secondvector.begin(),secondvector.end(),back_inserter(firstvector));
vector<int>::iterator it;
for ( it = firstvector.begin(); it!= firstvector.end(); ++it )
cout << *it << " ";//输出:1 2 3 4 5 10 20 30 40 50
cout << endl;
return 0;
}
secondvector中的内容最后插入到firstvector的后面。
(4)front_inserter
返回一个前向插入迭代器
原型:
template <class Container>
front_insert_iterator<Container> front_inserter (Container& x);
(5)inserter
返回一个插入迭代器
原型:
template <class Container, class Inserter>
insert_iterator<Container> inserter (Container& x, Inserter i);
一个例子如下:
#include <iostream>
#include <iterator>
#include <list>
using namespace std;
int main () {
list<int> firstlist, secondlist;
for (int i=1; i<=5; i++)
{ firstlist.push_back(i); secondlist.push_back(i*10); }
list<int>::iterator it;
it = firstlist.begin(); advance (it,3);
copy (secondlist.begin(),secondlist.end(),inserter(firstlist,it));
for ( it = firstlist.begin(); it!= firstlist.end(); ++it )
cout << *it << " ";//输出:1 2 3 10 20 30 40 50 4 5
cout << endl;
return 0;
}
3. 预定义的迭代器/迭代器适配器
STL提供了许多基于迭代器的适配器,如back_insert_iterator, front_insert_iterator, inser_iterator, reverse_iterator, istream_iterator, ostream_iterator, istreambuf_iterator, ostreambuf_iterator等。
输入输出迭代器的思想是将输入输出流当作序列,ostream_iterator和istream_iterator相当于指向序列的迭代器,用户可以通过这个迭代器对输入输出流做操作。但是,ostream_iterator的迭代器类型是input_iterator,只支持写操作(*p=X)和迭代操作(++);istream_iterator的迭代器类型是output_iterator,它可以支持读(=*p), 访问(->),迭代(++),比较(==, !=)操作。
(1). istream_iterator输入流迭代器
内部绑定了一个istream流对象,实现了前向迭代操作++和读取流数据的*操作。结果是从istream读出。
类定义如下:
template <class T, class charT=char, class traits=char_traits<charT>, class Distance=ptrdiff_t>
class istream_iterator :
public iterator<input_iterator_tag, T, Distance, const T*, const T&>
{
basic_istream<charT,traits>* in_stream;
T value;
public:
typedef charT char_type;
typedef traits traits_type;
typedef basic_istream<charT,traits> istream_type;
istream_iterator() : in_stream(0) {}
istream_iterator(istream_type& s) : in_stream(&s) { ++*this; }
istream_iterator(const istream_iterator<T,charT,traits,Distance>& x)
: in_stream(x.in_stream), value(x.value) {}
~istream_iterator() {}
const T& operator*() const { return value; }
const T* operator->() const { return &value; }
istream_iterator<T,charT,traits,Distance>& operator++() {
if (in_stream && !(*in_stream >> value)) in_stream=0;
return *this;
}
istream_iterator<T,charT,traits,Distance> operator++(int) {
istream_iterator<T,charT,traits,Distance> tmp = *this;
++*this;
return tmp;
}
};
值得注意的是istream_iterator中有一个标志标识输入序列是否结束,它的默认构造函数会将istream_iterator指向输入序列的结束位置(M_ok=false),表示输入序列结束。当对输入迭代器作迭代操作(++)的时候,会判断M_ok的值,如果该值为false,则终止读过程。
下面的一个例子可以实现数据的读取:
#include <iostream>
#include <iterator>
using namespace std;
int main () {
double value1, value2;
cout << "Please, insert two values: ";
istream_iterator<double> eos; // end-of-stream iterator
istream_iterator<double> iit (cin); // stdin iterator
if (iit!=eos) value1=*iit;
iit++;
if (iit!=eos) value2=*iit;
cout << value1 << "*" << value2 << "=" << (value1*value2) << endl;
return 0;
}
(2). ostream_iterator输出流迭代器
内部绑定一个ostream输出流对象,实现了Output Iterator的要求,提供了前向++迭代操作和=赋值写入操作。
类定义如下:
template <class T, class charT=char, class traits=char_traits<charT> >
class ostream_iterator :
public iterator<output_iterator_tag, void, void, void, void>
{
basic_ostream<charT,traits>* out_stream;
const charT* delim;
public:
typedef charT char_type;
typedef traits traits_type;
typedef basic_ostream<charT,traits> ostream_type;
ostream_iterator(ostream_type& s) : out_stream(&s), delim(0) {}
ostream_iterator(ostream_type& s, const charT* delimiter)
: out_stream(&s), delim(delimiter) { }
ostream_iterator(const ostream_iterator<T,charT,traits>& x)
: out_stream(x.out_stream), delim(x.delim) {}
~ostream_iterator() {}
ostream_iterator<T,charT,traits>& operator= (const T& value) {
*out_stream << value;
if (delim!=0) *out_stream << delim;
return *this;
}
ostream_iterator<T,charT,traits>& operator*() { return *this; }
ostream_iterator<T,charT,traits>& operator++() { return *this; }
ostream_iterator<T,charT,traits>& operator++(int) { return *this; }
};
这一个使用的比较多,经常和copy配合来完成容器元素的输出。
(3). istreambuf_iterator和ostreambuf_iterator
用于缓冲区的读取和写入。istreambuf_iterator和ostreambuf_iterator可以使用户跨过iostream,直接跟流缓冲区打交道。
istreambuf_iterator是相当于所有的输入都读入到缓冲区,然后从缓冲区不断得到所有的输入字符,不会考虑什么空白。
你可以像istream_iterator一样使用istreambuf_iterator,但istream_iterator<char>对象使用operator<<来从输入流中读取单个字符。istreambuf_iterator<char>对象进入流的缓冲区并直接读取下一个字符。(更明确地说,一个istreambuf_iterator<char> 对象从一个istream s中读取会调用s.rdbuf()->sgetc()来读s的下一个字符。)
(4). front_iterator前向插入迭代器
是架构在具有push_front向前插入函数的序列容器上的Output Iterator.
其实现如下:
template <class Container>
class front_insert_iterator :
public iterator<output_iterator_tag,void,void,void,void>
{
protected:
Container* container;
public:
typedef Container container_type;
explicit front_insert_iterator (Container& x) : container(&x) {}
front_insert_iterator<Container>& operator= (typename Container::const_reference value)
{ container->push_front(value); return *this; }
front_insert_iterator<Container>& operator* ()
{ return *this; }
front_insert_iterator<Container>& operator++ ()
{ return *this; }
front_insert_iterator<Container> operator++ (int)
{ return *this; }
};
(5). back_insert_iterator 向后插入迭代器
也是一个Output Iterator,架构在具有push_back函数的容器上。
源代码:
template <class Container>
class back_insert_iterator :
public iterator<output_iterator_tag,void,void,void,void>
{
protected:
Container* container;
public:
typedef Container container_type;
explicit back_insert_iterator (Container& x) : container(&x) {}
back_insert_iterator<Container>& operator= (typename Container::const_reference value)
{ container->push_back(value); return *this; }
back_insert_iterator<Container>& operator* ()
{ return *this; }
back_insert_iterator<Container>& operator++ ()
{ return *this; }
back_insert_iterator<Container> operator++ (int)
{ return *this; }
};
(6)insert_iterator插入迭代器
架构在具有insert函数的容器之上。
类定义如下:
template <class Container>
class insert_iterator :
public iterator<output_iterator_tag,void,void,void,void>
{
protected:
Container* container;
typename Container::iterator iter;
public:
typedef Container container_type;
explicit insert_iterator (Container& x, typename Container::iterator i)
: container(&x), iter(i) {}
insert_iterator<Container>& operator= (typename Container::const_reference value)
{ iter=container->insert(iter,value); ++iter; return *this; }
insert_iterator<Container>& operator* ()
{ return *this; }
insert_iterator<Container>& operator++ ()
{ return *this; }
insert_iterator<Container> operator++ (int)
{ return *this; }
};
(7). reverse_iterator反向迭代器
是用随机访问迭代器构造出来的迭代器。
反向迭代器reverse_iterator是一种反向遍历容器的迭代器,也就是从最后一个元素到第一个元素遍历容器。反向迭代器的自增(或自减)的含义反过来了:对于反向迭代器,++运算符将访问前一个元素,–运算符将访问下一个元素。
大部分容器都提供了rbegin和rend迭代器来支持反向迭代器进行反向遍历容器。
参考: http://www.cnblogs.com/cobbliu/archive/2012/04/17/2440347.html
http://blog.csdn.net/bichenggui/article/details/4710996