C++抽象编程——STL实战(1)——迭代器详解

来源:互联网 发布:sql 删除标识列 编辑:程序博客网 时间:2024/05/08 07:38

这篇博文我来谈谈迭代器(Iterator)——这个在STL中频频出现的专业词汇,为什么可以如此的重要。为此我不敢百度,因为我看了百度百科,但是很可惜答案我还是不满意,去维基了一下,中文版跟英文版相差太多了,这使得我又不得不硬着头皮去看英文版,接下来的大多数的内容都是来着自于wikipedia,我只是自己经验加上总结,对于C++的看法。要详细版的就点这个:https://en.wikipedia.org/wiki/Iterator

迭代器的由来:

在计算机编程中,Iterator是使程序员能够遍历容器的对象,特别是list。我们通常通过容器的界面提供各种类型的迭代器。虽然我们给定迭代器的接口和语义是固定的,但是迭代器通常是根据容器实现的结构来实现的,(例如我们之前的vector例子):

vector<int>::iterator it;

请注意,迭代器不仅仅可以执行遍历,并且还允许访问容器中的数据元素,但不执行迭代。迭代器在行为上类似于数据库上的游标(cursor)。迭代器首次的出现还得追溯到1974年的CLU编程语言。

迭代器的分类

  1. Internal Iterators(内部迭代器)
    内部迭代器是高阶函数(higher order functions)(通常采取匿名函数(anonymous functions)),例如map,reduce等,实现跨容器的遍历,依次将给定的函数应用于每个元素。但是我们现在不需要了解那么多的这个
  2. External iterators(外部迭代器)
    这个才是我们广泛意义上的迭代器。外部迭代器可以被认为是具有两个主要操作的指针类型:引用对象集合中的一个特定元素(即元素访问),并修改自身,以便它指向下一个元素(称为元素遍历)。还有一种创建迭代器的方法,以便它指向一些第一个元素以及确定迭代器何时耗尽容器中所有元素的方法。(即我们常说的指向起始位置和终止位置)根据语言和预期用途,迭代器还可以提供额外的操作或展示不同的行为。

注意:迭代器的主要目的是允许用户处理容器的每个元素,同时将用户与容器的内部结构隔离。 这允许容器以任何希望的方式存储元素,同时允许用户将其视为简单的序列或列表。 迭代器类通常与相应的容器类紧密配合。通常,容器提供了创建迭代器的方法。(就像我们上面的代码,vector对应这个容器的迭代器

一些经典的C++迭代器

迭代器可以根据其功能进行分类。

Category(分类) Languages Bidirectional iterator(双向迭代器) C++ Forward iterator(前向迭代器) C++ Input iterator(输入迭代器) C++ Output iterator(输出迭代器) C++ Random access iterator(随机访问迭代器) C++ Trivial iterator(遍历迭代器) C++ (old STL)

STL中的迭代器

C++在STL中广泛使用迭代器,它提供了多种不同类型的迭代器,包括前向迭代器,双向迭代器和随机存取迭代器。所有的标准容器模板类型都提供了丰富且一致的迭代器类型。标准迭代器的语法被设计为类似于普通C指针算术的语法,其中使用 * 和 -> 运算符来引用迭代器所指向的元素,并且使用诸如++的指针算术运算符将迭代器推送到下一个元素.
迭代器通常成对使用,其中一个用于实际的迭代,第二个用于标记集合的结束。迭代器由相应的容器类使用诸如begin()和end()之类的标准方法创建。由begin()返回的迭代器指向第一个元素,而由end()返回的迭代器是不引用任何元素的特殊值。当迭代器超出最后一个元素时,它的定义等于特殊的结束迭代器值。(所以我们说end()指向的是最后一个元素的后一位)
举个例子,我们看看下面的图:

这个图代表一个栈,base指针一直指向我们的最底层元素A,top指针一直指向最后一个元素C的上端。这个时候我们遍历这个栈,那么我们stack.begin()就相当于我们的base指针,stack.end()就相当于我们的top指针。
至于示例,那就去看我的文章C++抽象编程——STL(5)——set集合的基本输入输出 这里就用到了迭代器进行的输入输出。

迭代器的应用

迭代器有很多种,每种迭代器的行为略有不同,包括:前向,反向和双向迭代器;随机访问迭代器;输入和输出迭代器;和const迭代器(保护容器或其元素不被修改)。在这里说一下隐式迭代(Implicit iteration),意思就是说,我们看不到迭代的过程,但是在这个方法或者函数里面它确实进行了迭代,就比如我们之前提到过的sort方法

sort(vec.begin(),vec.end());

这里面肯定进行了迭代,不遍历全部元素怎么排序?只是我们看不到。这里还有一个很有用的函数。我们称为for_each()。它的功能以后我们再说。

0 0