标准C++中的Iterator(迭代器)

转载 2008年09月29日 21:52:00

一、概述
Iterator(迭代器)模式又称Cursor(游标)模式,用于提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。或者这样说可能更容易理解:Iterator模式是运用于聚合对象的一种模式,通过运用该模式,使得我们可以在不知道对象内部表示的情况下,按照一定顺序(由iterator提供的方法)访问聚合对象中的各个元素。
由于Iterator模式的以上特性:与聚合对象耦合,在一定程度上限制了它的广泛运用,一般仅用于底层聚合支持类,如STL的list、vector、stack等容器类及ostream_iterator等扩展iterator。
根据STL中的分类,iterator包括:
Input Iterator:只能单步向前迭代元素,不允许修改由该类迭代器引用的元素。
Output Iterator:该类迭代器和Input Iterator极其相似,也只能单步向前迭代元素,不同的是该类迭代器对元素只有写的权力。
Forward Iterator:该类迭代器可以在一个正确的区间中进行读写操作,它拥有Input Iterator的所有特性,和Output Iterator的部分特性,以及单步向前迭代元素的能力。
Bidirectional Iterator:该类迭代器是在Forward Iterator的基础上提供了单步向后迭代元素的能力。
Random Access Iterator:该类迭代器能完成上面所有迭代器的工作,它自己独有的特性就是可以像指针那样进行算术计算,而不是仅仅只有单步向前或向后迭代。
vector 和deque提供的是RandomAccessIterator,list提供的是BidirectionalIterator,set和map提供的 iterators是 ForwardIterator,关于STL中iterator的更多信息。

二、应用
Iterator模式有三个重要的作用:
1
)它支持以不同的方式遍历一个聚合 复杂的聚合可用多种方式进行遍历,如二叉树的遍历,可以采用前序、中序或后序遍历。迭代器模式使得改变遍历算法变得很容易: 仅需用一个不同的迭代器的实例代替原先的实例即可,你也可以自己定义迭代器的子类以支持新的遍历,或者可以在遍历中增加一些逻辑,如有条件的遍历等。
2
)迭代器简化了聚合的接口 有了迭代器的遍历接口,聚合本身就不再需要类似的遍历接口了,这样就简化了聚合的接口。
3
)在同一个聚合上可以有多个遍历 每个迭代器保持它自己的遍历状态,因此你可以同时进行多个遍历。
4
)此外,Iterator模式可以为遍历不同的聚合结构(需拥有相同的基类)提供一个统一的接口,即支持多态迭代。
简 单说来,迭代器模式也是Delegate原则的一个应用,它将对集合进行遍历的功能封装成独立的Iterator,不但简化了集合的接口,也使得修改、增 加遍历方式变得简单。从这一点讲,该模式与Bridge模式、Strategy模式有一定的相似性,但Iterator模式所讨论的问题与集合密切相关, 造成在Iterator在实现上具有一定的特殊性,具体将在示例部分进行讨论。

三、优缺点
正如前面所说,与集合密切相关,限制了 Iterator模式的广泛使用,就个人而言,我不大认同将Iterator作为模式提出的观点,但它又确实符合模式“经常出现的特定问题的解决方案”的 特质,以至于我又不得不承认它是个模式。在一般的底层集合支持类中,我们往往不愿“避轻就重”将集合设计成集合 + Iterator 的形式,而是将遍历的功能直接交由集合完成,以免犯了“过度设计”的诟病,但是,如果我们的集合类确实需要支持多种遍历方式(仅此一点仍不一定需要考虑 Iterator模式,直接交由集合完成往往更方便),或者,为了与系统提供或使用的其它机制,如STL算法,保持一致时,Iterator模式才值得考 虑。

四、举例
可以考虑使用两种方式来实现Iterator模式:内嵌类或者友元类。通常迭代类需访问集合类中的内部数据结构,为此,可在集合类中设置迭代类为friend class,但这不利于添加新的迭代类,因为需要修改集合类,添加friend class语句。也可以在抽象迭代类中定义protected型的存取集合类内部数据的函数,这样迭代子类就可以访问集合类数据了,这种方式比较容易添加新的迭代方式,但这种方式也存在明显的缺点:这些函数只能用于特定聚合类,并且,不可避免造成代码更加复杂。

STL的list::iterator、deque::iterator、rbtree::iterator等采用的都是外部Iterator类的形式,虽然STL的集合类的iterator分散在各个集合类中,但由于各Iterator类具有相同的基类,保持了相同的对外的接口(包括一些traits及tags等,感兴趣者请认真阅读参考12),从而使得它们看起来仍然像一个整体,同时也使得应用algorithm成为可能。我们如果要扩展STL的iterator,也需要注意这一点,否则,我们扩展的iterator将可能无法应用于各algorithm。

五、代码

#include <assert.h>

#include <iostream>
#include <xutility>
#include <iterator>
#include <algorithm>
using namespace std;

template
<typename T>
class
BinaryTree;
template
<typename T>
class
Iterator;

template
<typename T>
class
BinaryTreeNode
{

public
:
     typedef
BinaryTreeNode<T> NODE;
     typedef
BinaryTreeNode<T>* NODE_PTR;

     BinaryTreeNode(const T& element) : data(element), leftChild(NULL), rightChild(NULL), parent(NULL) { }
     BinaryTreeNode(const T& element, NODE_PTR leftChild, NODE_PTR rightChild)
         :
data(element), leftChild(leftChild), rightChild(rightChild), parent(NULL)
     {

         if
(leftChild)
             leftChild->setParent(this);
         if
(rightChild)
             rightChild->setParent(this);
     }

    
     T getData(void) const { return data; }
     NODE_PTR getLeft(void) const { return leftChild; }
     NODE_PTR getRight(void) const { return rightChild; }
     NODE_PTR getParent(void) const { return parent; }
     void
SetData(const T& data) { this->data = item; }
     void
setLeft(NODE_PTR ptr) { leftChild = ptr; ptr->setParent(this); }
     void
setRight(NODE_PTR ptr) { rightChild = ptr; ptr->setParent(this); }
     void
setParent(NODE_PTR ptr) { parent = ptr; }
private
:
     T data;
     NODE_PTR leftChild;
     NODE_PTR rightChild;
     NODE_PTR parent;   // pointer to parent node, needed by iterator

     friend class
BinaryTree<T>;
};

C++迭代器(iterator)的简单使用

迭代器提供对一个容器中的对象的访问方法,并且定义了容器中对象的范围。迭代器就如同一个指针。事实上,C++的指针也是一种迭代器。但是,迭代器不仅仅是指针,因此你不能认为他们一定具有地址值。例如,一个数组...
  • Icarus_
  • Icarus_
  • 2016年03月20日 20:41
  • 3251

[C++]List with iterator(链表的迭代器实现)

List with iterator(链表的迭代器实现)我们都知道STL容器内部都有相应的迭代器,本文主要讨论的就是链表内部的迭代器实现。测试代码#include #include using n...
  • stary_yan
  • stary_yan
  • 2016年05月30日 16:21
  • 2986

C++标准模板库 迭代器 iterator 详解(一)

[cpp] view plaincopyprint? #include    #include    #include    #include    #inclu...
  • imxiangzi
  • imxiangzi
  • 2015年11月14日 16:15
  • 1630

TCPL C++迭代器的用法 用作参数传递 读写文件

C++数据流迭代器(iterators)一般不直接使用,而是用做某些算法的参数。这些算法多是STL中的算法,是用C习惯了的朋友,应该会觉得这个有点不需太习惯,但是这就是C++的方法,据C++之父Bej...
  • kenden23
  • kenden23
  • 2013年10月21日 08:57
  • 2792

C++学习之Pair和迭代器 iterator的使用方法

C++学习之Pair的使用方法 一、Pair类型概述 pair是一种模板类型,其中包含两个数据值,两个数据的类型可以不同,基本的定义如下: pair a; 表示a中有两个类型,第一个元素...
  • m0_37407756
  • m0_37407756
  • 2017年12月26日 21:47
  • 49

迭代器(Iterator)

迭代器(Iterator)是一个对象,它的工作是遍历并选择序列中的对象,它提供了一种访问一个容器(container)对象中的各个元素,而又不必暴露该对象内部细节的方法。通过迭代器,开发人员不需要了解...
  • Dove_Knowledge
  • Dove_Knowledge
  • 2017年04月30日 16:45
  • 1007

C++ map迭代器的基本操作和使用

1、map简介 map是一类关联式容器。它的特点是增加和删除节点对迭代器的影响很小,除了那个操作节点,对其他的节点都没有什么影响。对于迭代器来说,可以修改实值,而不能修改key。 2、ma...
  • cyangc
  • cyangc
  • 2014年04月14日 14:14
  • 9415

C++ 自定义迭代器

程序员可以根据需要定义自己的迭代器。MyIterator //print.h #include #include template inline void PRINT_ELEMENTS(cons...
  • Slience_Perseverance
  • Slience_Perseverance
  • 2014年03月12日 19:44
  • 3707

容器vector list queue 迭代器iterator

一、容器 作为STL的最主要组成部分--容器,分为向量(vector),双端队列(deque),表(list),队列(queue),堆栈(stack),集合(set),多重集合(multiset),...
  • jgl841001
  • jgl841001
  • 2012年11月14日 11:07
  • 3738

通过reverse_iterator的base()得到iterator

调用reverse_iterator的base成员函数可以产生“对应的”iterator。 vector v; v.reserve(5); for(int i = 0;i < 5; ++ i) { /...
  • ww32zz
  • ww32zz
  • 2015年08月14日 18:33
  • 965
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:标准C++中的Iterator(迭代器)
举报原因:
原因补充:

(最多只允许输入30个字)