现在的位置: 首页 > 综合 > 正文

C++ stl之迭代器(iterator)

2013年08月14日 ⁄ 综合 ⁄ 共 3141字 ⁄ 字号 评论关闭

经过前面对各容器的讲解,相信大家已经对迭代器有一定的了解了,迭代器作为STL中的几大模块之一(系统工具,容器,迭代器,算法,仿函数,string以及iostream),重要性毋庸置疑,现在我们来详细的讨论分析STL中迭代器的用法。

迭代器产生动机:

在早期STL 的实现中,容器和算法是合并在一起的,即每个容器都有他的专属算法,但是后来发现这样效率不高,而且每个容器的很多算法都是大致相同的,于是STL的设计者萌生了把算法和容器分开的想法,即算法只写一次,每个容器都可以调用。从而需要在容器和算法之间需要一个中间变量充当桥梁,由此,迭代器应运而生了。

 

 

请注意,上面的图表关系并不代表继承关系,只是下面是上面的扩充集

(因为STL中的迭代器现在只用最后两种,前三种只做简单介绍)

Input_iterator (输入迭代器):输入迭代器只能向前一步一步向前读取元素,而且一个位置只能读一次。

Output_iterator(输出迭代器):输出迭代器只能用来向前一步一步写入元素,一个位置只能写入一次。

Forward_iterator(前向迭代器):前向迭代器基本能做输入输出迭代器可以做的一切事情,既可以读取,也可以写入,而且还可以多次,但是没变的是也只能一步一步的向前,不可跨越。

Bidirectional iterators(双向迭代器):双向迭代器在前向迭代器的基础上做了修改,增加了后退的操作,所以叫双向,同时也保存了前向迭代器的一切特性,但是也只能一步一步的操作,不可跨越,支持他的容器有List set multiset map multimap 

注意:双向迭代器本身只能支持++ —— !=  == 操作,不能如下这样使用:

List<int> coll;

List<int>::iterator it;

For(it=coll.begin();it<coll.end();it+1)     //error

```````````````````````````````````````

第一个错误在于it<coll.end();双向迭代器不支持<操作符。

第二个错误在于 it+1;双向迭代器只能it++

所以必须这样写:

For(it=coll.begin();it!=coll.end();it++) 

其实也不能想像,在list是由链表实现的,链表访问任何一个位置的元素都只能从表头依次读取下去,不能直接访问那个元素,其他几个容器类似。

Random access iterators(随机存取迭代器):

随机存取迭代器在双向迭代器的基础上在增加了随机存取的能力,他可以增加某个偏移量或减去某偏移量,能处理距离的问题并运用< >运算符,也可以像数组一样随机的访问或者修改某个元素,是现在迭代器的最高进化版本。如果把上面那个错误例子的list改为vector,那就正确。随机存取迭代器跟一般的指针支持的运算一致。他支持的容器是vector deque..

迭代器几个相关辅助函数:

1advance() 可令迭代器前进或者后退指定的位。

template<class InIt, class Dist>

void advance(InIt& it, Dist n);

第一个参数是传入迭代器,第二个参数一般是整数,如果为正,则表示前进n位,反之则后退n位。(注意在迭代器中往后走代表前进,往前走代表后退)

 

 

2distance() 可以处理两个迭代器之间的位置。

template<class Init, class Dist>

    ptrdiff_t distance(InIt first, InIt last);

该函数传入两个迭代器,返回他们相隔的距离,但是务必保证两个迭代器一定要是同一个容器上的,否则导致未定义行为。

3iter_swap 可以交换两个迭代器所指的的值(迭代器位置不变)

template<class FwdIt1, class FwdIt2>

void iter_swap(FwdIt1 x, FwdIt2 y);

两个参数为两个迭代器,执行完后所指的值被交换。

相信到这里,大家也许会疑惑,随机存储迭代器可以直接相减求距离,也可以直接相加,也可直接交换,那为什么还要这几个函数,其实这几个函数主要是为非随机存取迭代器服务的,因为他们本身不具有这些功能,当他们用于随机存取迭代器,执行的跟我们自己操作的一样,具有常数复杂度,用于双向迭代器的具有对数复杂度。

下面我们针对前面所讲的举一个简单的例子:

#include<iostream>

#include<vector>

#include<list>

#include<algorithm>

using namespace std;

int main()

{

vector<int> vec;

list<int> lis;

for(int by=1;by<21;++by)

{

vec.push_back(by);

lis.push_back(by);

}

vector<int>::iterator it1,it2;

list<int>::iterator io1,io2;

cout<<"对于distance()的用法:"<<endl;

it1=find(vec.begin(),vec.end(),3);

io1=find(lis.begin(),lis.end(),3);

it2=find(vec.begin(),vec.end(),13);

io2=find(lis.begin(),lis.end(),13); 

cout<<"vector中的相距位置:"<<(it2-it1)<<endl;

cout<<"list中的相距位置:"<<distance(io1,io2)<<endl<<endl;

cout<<"对于advance()的用法:"<<endl;

cout<<"vector中的相距位置:"<<(it2+3)-(it1+2)<<endl;

advance(io1,2);

advance(io2,3);

cout<<"list中的相距位置:"<<distance(io1,io2)<<endl<<endl;

cout<<"对于iter_swap()的用法:"<<endl;

cout<<"vector中利用中间变量交换"<<endl;

int mid;

mid=*(it1+2);

*(it1+2)=*(it2+3);

*(it2+3)=mid;

copy(vec.begin(),vec.end(),ostream_iterator<int>(cout," "));

cout<<endl;

cout<<"list中利用iter_swap()交换:"<<endl;

iter_swap(io1,io2);

copy(lis.begin(),lis.end(),ostream_iterator<int>(cout," "));

cout<<endl;

  system("pause");

return 0;

}

 

 

对于这个例子,其实就是分别存储120的数字在两个不同类型的容器中(当然这里主要是指他们的不同迭代器)。然后分别找到313的迭代器位置,vector中可以直接相减得出距离,list只能用distance函数,分别偏移相同的单位,在算出距离。最后交换迭代器所指的内容,很明显165的位置改变了。

这个小程序很简单,但是他所体现出来的两种迭代器的不同点却是显然的,一般迭代器辅助函数我们都只对双向迭代器使用,因为随机存取迭代器没必要,但是也要看实际情况而定!讲到这里,主要问题就是理解随机存取迭代器和双向迭代器的区别,关于他们更多的区别,在算法中还会提到。

 

 

 

 

 

 

抱歉!评论已关闭.