STL六大组件之——迭代器这个东西

迭代器:除了在其它语言中司空见惯的下标法访问容器元素之外,C++语言提供了一种全新的方法——迭代器(iterator)来访问容器的元素。迭代器其实类似于引用,指向容器中某一元素。换个方式来说,容器就是数据结构的泛指,迭代器就是指针的泛指,可以指向元素。容器相当于一个储藏柜,里面装的许多不同的物品就像是储存的元素,比如面包、啤酒、苹果、现金。要取得各个物体就得用与各个物体向匹配的工具,如取出面包要用盘子、取出啤酒要用杯子、取出苹果要用篮子、取出现金要用钱包。迭代器的作用就相当于取出物品的工具的抽象,通过迭代器泛指现实生活中从贮藏室中取出物体的工具。C++迭代器是一种检查容器内元素并遍历元素的数据类型。

迭代器的类型

对于STL数据结构和算法,你可以使用五种迭代器。下面简要说明了这五种类型:

Input iterators 提供对数据的只读访问。

Output iterators 提供对数据的只写访问。

Forward iterators 提供读写操作,并能向前推进迭代器。

Bidirectional iterators提供读写操作,并能向前和向后操作。

Random access iterators提供读写操作,并能在数据中随机移动。

尽管各种不同的STL实现细节方面有所不同,还是可以将上面的迭代器想象为一种类继承关系。从这个意义上说,下面的迭代器继承自上面的迭代器。由于这种继承关系,你可以将一个Forward迭代器作为一个output或input迭代器使用。同样,如果一个算法要求是一个bidirectional 迭代器,那么只能使用该种类型和随机访问迭代器。

指针迭代器

一个指针也是一种迭代器。该程序同样显示了STL的一个主要特性——它不只是能够用于它自己的类类型,而且也能用于任何C或C++类型。下面的程序显示了如何把指针作为迭代器用于STL的find()算法来搜索普通的数组。

 1 #include <iostream.h>
 2 #include <algorithm>
 3 
 4 using namespace std;
 5 #define SIZE 100
 6 int iarray[SIZE];
 7 
 8 int main()
 9 {
10   iarray[20] = 50;
11   int* ip = find(iarray, iarray + SIZE, 50);
12   if (ip == iarray + SIZE)
13      cout << "50 not found in array" << endl;
14   else
15      cout << *ip << " found in array" << endl;
16   return 0;
17 }

程序中定义了尺寸为SIZE的全局数组。由于是全局变量,所以运行时数组自动初始化为零。下面的语句将在索引20位置处地元素设置为50,并使用find()算法来搜索值50:

iarray[20] = 50;

int* ip = find(iarray, iarray + SIZE, 50);

find()函数接受三个参数。头两个定义了搜索的范围。由于C和C++数组等同于指针,表达式iarray指向数组的第一个元素。而第二个参数iarray + SIZE等同于past-the-end 值,也就是数组中最后一个元素的后面位置。第三个参数是待定位的值,也就是50。find()函数返回和前两个参数相同类型的迭代器,这儿是一个指向整数的指针ip。

if (ip == iarray + SIZE) ...

如果表达式为真,则表示在搜索的范围内没有指定的值。否则就是指向一个合法对象的指针,这时可以用下面的语句显示::

cout << *ip << " found in array" << endl;

测试函数返回值和NULL是否相等是不正确的。不要象下面这样使用:

int* ip = find(iarray, iarray + SIZE, 50);

if (ip != NULL) ...  // ??? incorrect

当使用STL函数时,只能测试ip是否和past-the-end 值是否相等。尽管在本例中ip是一个C++指针,其用法也必须符合STL迭代器的规则。

容器迭代器

尽管C++指针也是迭代器,但用的更多的是容器迭代器。和将迭代器申明为指针变量不同的是,你可以使用容器类方法来获取迭代器对象。两个典型的容器类方法是begin()和end()。它们在大多数容器中表示整个容器范围。其他一些容器还使用rbegin()和rend()方法提供反向迭代器,以按反向顺序指定对象范围。

下面的程序创建了一个矢量容器(STL的和数组等价的对象),并使用迭代器在其中搜索。该程序和前一章中的程序相同。

 1 #include <iostream.h>
 2 #include <algorithm>
 3 #include <vector>
 4 
 5 using namespace std;
 6 vector<int> intVector(100);
 7 
 8 void main()
 9 {
10   intVector[20] = 50;
11   vector<int>::iterator intIter =
12   find(intVector.begin(), intVector.end(), 50);
13   if (intIter != intVector.end())
14      cout << "Vector contains value " << *intIter << endl;
15   else
16      cout << "Vector does not contain 50" << endl;
17 }

常量迭代器

和指针一样,你可以给一个迭代器赋值。例如,首先申明一个迭代器:

vector<int>::iterator first;

该语句创建了一个vector<int>类的迭代器。下面的语句将该迭代器设置到intVector的第一个对象,并将它指向的对象值设置为123::

first = intVector.begin();

*first = 123;

这种赋值对于大多数容器类都是允许的,除了只读变量。为了防止错误赋值,可以申明迭代器为:

const vector<int>::iterator result;

result = find(intVector.begin(), intVector.end(), value);

if (result != intVector.end())

*result = 123;  // ???

//警告:另一种防止数据被改变得方法是将容器申明为const类型。

具体迭代器的实现源码,https://www.sgi.com/tech/stl/download.html上有,可以自己下来看看。

原文地址:https://www.cnblogs.com/geekpaul/p/4166925.html