迭代器(iterator)是连接容器和算法的纽带,为数据提供了抽象,使写算法的人不必关心各种数据结构的细节。迭代器提供了数据访问的标准模型——对象序列,使对容器更广泛的访问操作成为可能。
根据迭代器所支持的操作不同,在STL中定义了如下5种迭代器:
迭代器类别 | 说明 |
输入 | 从容器中读取元素。输入迭代器只能一次读入一个元素向前移动,输入迭代器只支持一遍算法,同一个输入迭代器不能遍历一个序列两遍 |
输出 | 向容器中写入元素。输出迭代器只能一次一个元素向前移动。输出迭代器只支持一遍算法,同一输出迭代器不能两次遍历一个序列 |
正向 | 具有输入迭代器的全部功能和输出迭代器的大部分功能 |
双向 | 具有正向迭代器和逆向迭代器的功能,支持多遍算法 |
随机访问 |
具有双向迭代器的功能与直接访问容器中任何元素的功能,即可向前向后跳过任意个元素 |
迭代器的层次结构:
上面这图表并不是表明它们之间的继承关系:而只是描述了迭代器的种类和接口。
迭代器能力:
|
输入 |
输出 |
前向 |
双向 |
随机访问 |
|
读取(= *i) |
|
√ |
× |
√ |
√ |
√ |
写入(*i =) |
|
× |
√ |
√ |
√ |
√ |
多通 |
|
× |
× |
√ |
√ |
√ |
++i和i++ |
|
√ |
√ |
√ |
√ |
√ |
--i和i-- |
|
× |
× |
× |
√ |
√ |
i[n] |
|
× |
× |
× |
× |
√ |
i + n和i - n |
|
× |
× |
× |
× |
√ |
i += n和i -= n |
|
× |
× |
× |
× |
√ |
==和 != |
|
√ |
× |
√ |
√ |
√ |
<和 > |
|
× |
× |
× |
× |
√ |
<=和 >= |
|
× |
× |
× |
× |
√ |
迭代器多通是指以同样的顺序来遍历容器,而且迭代器递增后,仍然可以通过解除保存的迭代器引用,来获得同样的值。
为何Forward迭代器不具备Output迭代器的全部功能?
这是因为有一个约束条件,使得某些对Output Iterator有效的程序对Forward Iterator可能无效。
-
面对Output Iterator无须检查其是否抵达序列尾端,便可直接写入数据。事实上由于Output Iterator不提供比较操作,因此无法将Output Iterator与end-of-sequence相比较。以下循环是正确的:
while(true)
{
*pos = foo();
++pos;
} -
对于Forward Iterator,必须在提领数据之前确保其有效,因此上述循环对Forward Iterator是错误的。对于Forward Iterator上述循环应改为:
while( pos != coll.end() )
{
*pos = foo();
++pos;
}
而同时,该循环不适用于Output Iterator,因为Output Iterator没有operator!=
*将迭代器移至“起点更前面或end()之后”都会引起未定义行为。
vecotr迭代器的递增和递减
迭代器的递增和递减操作有个奇怪的问题。一般而言你可以递增或递增暂时性迭代器,但对于vectors和strings就不行,如下:
vector<int> coll;
coll.push_back(1);
coll.push_back(3);
coll.push_back(2);
coll.push_back(4);
if (coll.size() > 1)
{
sort(++coll.begin(), coll.end()); //vs2013下能运行,因为实现为模板class
}
copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));
C++不允许你修改任何基本型别(包括指针)的暂时值,但对于struct和class则允许。因此如果迭代器被实作为一般指针,上面代码编译会失败。如编译不通过可以改为:
vector<int>::iterator it = coll.begin();
sort(++it, coll.end());
迭代器的辅助函数
#include<iterator>
void advance(InputIterator pos,int n);
不检查迭代器是否超过end(), 无返回值。
#include<iterator>
iterator_traits<InputIterator>::difference_type distance(InputIterator pos1,InputIterator pos2);
两个迭代器都必须指向同一个容器,从pos1必须能到达pos2
#include<algorithm>
void iter_swap(ForwardIteraor1 pos1,ForwardIteraor2 pos2);
迭代器型别不一定相同,但pos1和pos2的内容可相互赋值,交换迭代器pos1和pos2所指的值。