理解迭代器对于理解STL框架并掌握STL的使用至关重要。简单地说,迭代器是面向对象版本的指针,STL算法利用迭代器对存储在容器中的元素序列进行遍历,迭代器提供了访问容器和序列中每个元素的方法。

虽然指针也是一种迭代器,但迭代器却不仅仅是指针。指针可以指向内存中的一个地址,通过这个地址就可以访问相应的地址。而迭代器更为抽象,它可以指向容器中的一个位置,我们也许不必关心这个位置的真正物理地址,但是我们可以通过迭代器访问这个位置的元素。

迭代器是算法和容器的“中间人”,遍历链表需要指针,对数组元素进行排序要通过下标来访问数组元素。那么,指针和下标运算符便充当了算法和数据结构的“中间人”;在STL中,容器是封装起来的类模板,其内部结构无从知晓,我们只能通过容器接口来使用容器,但是STL中的算法是通用的函数模板,并不专门针对那一个容器类型。这时请想一想:算法要适用于多种容器,而每一种容器存放的元素又可以是任何类型,如何用普通的指针或下标类充当中介呢?使用指针需要直到其指向的元素类型,使用下标需要在相应的容器中定义过下标操作符,但不是每个容器中都有下标操作符的。这时就必须使用更为抽象的指针--迭代器。

就像我们声明指针时要说明其指向的元素一样,STL的每一个容器类模板中,都定义了一组对应的迭代器类。使用迭代器,算法函数可以访问容器中指定位置的元素,而无需关心元素的具体类型。

1、迭代器的类型

为了满足某些特定算法的需要,STL迭代器主要包括5种基本迭代器类别:输入、输出、前向、双向和随机访问,以及两种迭代器适配器:逆向迭代器适配器和插入迭代器适配器。

1)迭代器分类

输入迭代器对象可以用来从序列中读取数据,但是不一定能够向其中写入数据。输出迭代器具有刚好相反的功能,它允许向序列中写入数据,但是并不保证可以从其中读取数据。

前向迭代器既是输入迭代器又是输出迭代器,因此它即支持数据读取,也支持数据写入,并且可以对序列进行单向的遍历。

双向迭代器的功能与前向迭代器相似,不同之处在于,双向迭代器在两个方向上都可以对数据遍历。也就是说,双向迭代器必须支持前向迭代器的所有操作,此外,还必须支持双向操作,从而使对序列进行反向遍历。

随机访问迭代器也是双向迭代器,它对迭代器提供了更高的要求,能够在序列中的任意两个位置之间进行跳转。

2、迭代器适配器

适配器是用来修饰或调整其他类接口的,迭代器适配器便是用来扩展(或调整)迭代器功能的类。当然这样的适配器本身也称为迭代器,只是这种迭代器是通过改变另一个迭代器而得到的。STL中定义了两类迭代器适配器:

逆向迭代器是一种适配器,它通过重新定义递增运算和递减运算,使其行为正好倒置。这样,使用这类迭代器,算法将以逆向次序处理元素。所有标准容器都允许使用逆向迭代器来遍历元素。

插入型迭代器用来将赋值操作转换为插入操作。通过这种迭代器,算法可以执行插入行为而不是覆盖行为。c++标准程序库提供了3种插入型迭代器:后插入型迭代器、前插入型迭代器、普通插入型迭代器。

例子:

应用逆向迭代器和后插迭代器来操作向量容器中的元素

#include<iostream>
#include<vector>
#include<algorithm>
#include<iterator>
using namespace std;
int main()
{
 int A[] = {1,2,3,4,5};
 const int N = sizeof(A) / sizeof(int);
 vector<int> col1(A,A+N);
 ostream_iterator<int>output(cout," ");
 cout << "List col1 contains:";
 copy(col1.begin(),col1.end(),output);
 
 vector<int>::iterator pos = col1.begin();//定义指向初始元素的迭代器
 cout << "\nThe first element is:" << *pos;//输出第一个元素
 vector<int>::reverse_iterator rpos = col1.rbegin();//应用逆向迭代器指向最后一个元素
 cout << "\nThe last element is:" << *rpos << endl;//输出最后一个元素
 back_insert_iterator<vector<int>>iter(col1);//声明后插迭代器
 *iter = 66;//应用后插迭代器插入元素66
 back_inserter(col1) = 88;//应用函数后插入元素88
 copy(col1.begin(), col1.end(), output);//输出后插操作后的向量容器col1中的元素
 getchar();
 getchar();
 cout << endl;
}

2、迭代器相关的辅助函数

advance()、distance()两个提供了所有迭代器一些原本只有随机访问迭代器才有的访问能力:前进或后退多少个元素,以及处理迭代器之间的距离。iter_swap()函数允许用户交换两个迭代器的值。

void advance(InputIterator& pos,Dist n);

该函数使输入型迭代器前进(或后退)n个元素,对于双向或随机访问迭代器,可以取负值,表示向后访问。

dist distance(InputIterator pos1,InputIterator pos2);

该函数传回两个输入迭代器pos1和pos2之间的距离,两个迭代器必须指向同一个容器。如果不是随机访问迭代器,则从pos1开始往前走必须能够到达pos2,即pos2的位置必须与pos1相同或在后。

iter_swap()可以交换两个迭代器所指向的元素值。

void iter_swap(ForwardIterator1 pos1,ForwardIterator2 pos2);

该函数用于交换迭代器pos1和pos2所指向的元素值,迭代器的类型不必相同,但所只元素之间必须可以相互赋值。

#include<iostream>

#include<iterator>

#include<list>

#include<algorithm>

using namespace std;

int main() {

int A[] = {1,2,3,4,5};

const int N = sizeof(A) / sizeof(int);

list<int> col1(A, A + N);

ostream_iterator<int> output(cout," ");

cout << "List col1 contains:";

copy(col1.begin(),col1.end(),output);//输出初始列表容器col1中的元素

list<int>::iterator pos = col1.begin();//定义指向初始元素的迭代器

cout << "\nThe first element is:" << *pos;//输出第一个元素

advance(pos,3);//前进3个元素,指向第四个元素

cout << "\nThe 4th element is:" << *pos;//输出第4个元素

cout << "\nThe advanced distance is:" << distance(col1.begin(),pos);//输出当前迭代器位置与初始位置的距离

iter_swap(col1.begin(),--col1.end());//交换列表容器中第一个元素和最后一个元素

cout << "\nAfter exchange list col1 constains:";  copy(col1.begin(),col1.end(),output);//输出交换元素后列表容器col1中的元素

getchar();  getchar();

cout << endl;

}

8、泛型程序设计与c++标准模板库3.迭代器的更多相关文章

  1. 8、泛型程序设计与c++标准模板库1、泛型程序设计的概念和术语

    有效地利用已有的成果,将经典的.优秀的算法标准化.模块化,从而提高软件的生产率,是软件产业化的需求,为了实现这一需求,不仅需要面向对象设计思想,而且需要泛型程序设计思想. c++语言提供的标准模板库( ...

  2. 8、泛型程序设计与c++标准模板库4.标准c++库中的算法

    标准c++算法是通过迭代器和模板来实现的,其实算法本身就是一种函数模板. 算法从迭代器那里获得一个元素,而迭代器则知道一个元素在容器中的什么位置.迭代器查找元素的位置并将这些信息提供给算法以便算法能够 ...

  3. 8、泛型程序设计与c++标准模板库2、c++标准模板库中的容器

    顺序容器类以逻辑线性排列方式存储元素,在这些容器类型中的元素在逻辑上被认为是连续的存储空间中存储的.顺序容器可用于存储线性群体. 在关联容器类中,元素的存储和检索基于关键字和元素与其他元素之间的关系, ...

  4. C++学习笔记53:泛型程序设计与C++标准模板库

    泛型程序设计的基本概念 编写不依赖于具体数据类型的程序 将算法从特定的数据结构中抽象出来,成为通用的 C++模板为泛型编程程序设计奠定了关键的基础 模型:符合一个概念的数据类型称为该概念的模型,例如: ...

  5. 8、泛型程序设计与c++标准模板库2.5容器适配器

    容器适配器是用来扩展7中基本容器的,是修改和调整其他类接口的类.他们不提供存放数据的实际数据结构的实现方法,而且容器适配器也不支持迭代器. 1.标准栈容器 使用STL中的标准栈为程序员提供了一层附加的 ...

  6. 8、泛型程序设计与c++标准模板库5.函数对象

    1.函数对象 函数对象是STL提供的第四类主要组件,它使得STL的应用更加灵活方便,从而增强了算法的通用性.大多数STL算法可以用一个函数对象作为参数.所谓“函数对象”其实就是一个行为类似函数的对象, ...

  7. 8、泛型程序设计与c++标准模板库2.3双端队列容器

    双端队列容器是一种放松了访问权限的队列.除了从队列的首部和尾部访问元素外,标准的双端队列也支持通过使用下标操作符"[]"进行直接访问. 它提供了直接访问和顺序访问方法.其头文件为& ...

  8. 8、泛型程序设计与c++标准模板库2.2向量容器

    向量容器属于顺序容器,用于容纳不定长线性序列(即线性群体),提供对序列的快速随机访问(也称直接访问).这一点与c++语言支持的基本数组类型相同,但基本数据类型不是面向对象的.而面向对象的向量是动态结构 ...

  9. 第十章 泛型程序设计与C++标准模板库 泛型程序设计及STL的结构

随机推荐

  1. zabbix实现mysql数据库的监控(四)

    前面介绍的内容都是用第三方开发好的插件进行mysql监控的,可能有些我们关心的监控内容并不在其中,这时一种常用的方法就是定义我们自己的脚本并将它整合到zabbix中,从而在原有监控的基础上进行有力的补 ...

  2. ImportError: no module named win32api

    ImportError: no module named win32api 安装win32包就好了 pip install pypiwin32

  3. Java+MySql图片数据保存

    之前一直没有做过涉及到图片存储的应用,最近要做的东东涉及到了这个点,就做了一个小的例子算是对图片存储的初试吧! 1.创建表: drop table if exists photo; CREATE TA ...

  4. Spark- 求最受欢迎的TopN课程

    数据库操作工具类 package com.rz.mobile_tag.utils import java.sql.{Connection, DriverManager, PreparedStateme ...

  5. HIVE- 新建UDF范例

    首先pom文件导入依赖,Hadoop和hive的依赖导入自己机器的版本,hive记得导jdbc <dependency> <groupId>org.apache.hadoop& ...

  6. Luogu P1463 [HAOI2007]反素数ant:数学 + dfs【反素数】

    题目链接:https://www.luogu.org/problemnew/show/P1463 题意: 对于任何正整数x,其约数的个数记作g(x).例如g(1)=1.g(6)=4. 如果某个正整数x ...

  7. 创建第一个Servlet并定制Sevlet模板

    我们已经为eclipse配好了Tomcat服务器,创建了Web工程,现在是时候该创建一个Servlet向世界问好了! 第一步:创建一个Web工程,选中”src“文件夹 -->单击右键,鼠标移到” ...

  8. C. Jury Marks

    C. Jury Marks time limit per test 2 seconds memory limit per test 256 megabytes input standard input ...

  9. linux命令学习笔记(18):locate 命令

    locate 让使用者可以很快速的搜寻档案系统内是否有指定的档案.其方法是先建立一个包括系统内所有档案名称及 路径的数据库,之后当寻找时就只需查询这个数据库,而不必实际深入档案系统之中了.在一般的 d ...

  10. OpenCV——百叶窗

    参考: PS 图像特效,百叶窗 // define head function #ifndef PS_ALGORITHM_H_INCLUDED #define PS_ALGORITHM_H_INCLU ...