8、泛型程序设计与c++标准模板库3.迭代器
理解迭代器对于理解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.迭代器的更多相关文章
- 8、泛型程序设计与c++标准模板库1、泛型程序设计的概念和术语
有效地利用已有的成果,将经典的.优秀的算法标准化.模块化,从而提高软件的生产率,是软件产业化的需求,为了实现这一需求,不仅需要面向对象设计思想,而且需要泛型程序设计思想. c++语言提供的标准模板库( ...
- 8、泛型程序设计与c++标准模板库4.标准c++库中的算法
标准c++算法是通过迭代器和模板来实现的,其实算法本身就是一种函数模板. 算法从迭代器那里获得一个元素,而迭代器则知道一个元素在容器中的什么位置.迭代器查找元素的位置并将这些信息提供给算法以便算法能够 ...
- 8、泛型程序设计与c++标准模板库2、c++标准模板库中的容器
顺序容器类以逻辑线性排列方式存储元素,在这些容器类型中的元素在逻辑上被认为是连续的存储空间中存储的.顺序容器可用于存储线性群体. 在关联容器类中,元素的存储和检索基于关键字和元素与其他元素之间的关系, ...
- C++学习笔记53:泛型程序设计与C++标准模板库
泛型程序设计的基本概念 编写不依赖于具体数据类型的程序 将算法从特定的数据结构中抽象出来,成为通用的 C++模板为泛型编程程序设计奠定了关键的基础 模型:符合一个概念的数据类型称为该概念的模型,例如: ...
- 8、泛型程序设计与c++标准模板库2.5容器适配器
容器适配器是用来扩展7中基本容器的,是修改和调整其他类接口的类.他们不提供存放数据的实际数据结构的实现方法,而且容器适配器也不支持迭代器. 1.标准栈容器 使用STL中的标准栈为程序员提供了一层附加的 ...
- 8、泛型程序设计与c++标准模板库5.函数对象
1.函数对象 函数对象是STL提供的第四类主要组件,它使得STL的应用更加灵活方便,从而增强了算法的通用性.大多数STL算法可以用一个函数对象作为参数.所谓“函数对象”其实就是一个行为类似函数的对象, ...
- 8、泛型程序设计与c++标准模板库2.3双端队列容器
双端队列容器是一种放松了访问权限的队列.除了从队列的首部和尾部访问元素外,标准的双端队列也支持通过使用下标操作符"[]"进行直接访问. 它提供了直接访问和顺序访问方法.其头文件为& ...
- 8、泛型程序设计与c++标准模板库2.2向量容器
向量容器属于顺序容器,用于容纳不定长线性序列(即线性群体),提供对序列的快速随机访问(也称直接访问).这一点与c++语言支持的基本数组类型相同,但基本数据类型不是面向对象的.而面向对象的向量是动态结构 ...
- 第十章 泛型程序设计与C++标准模板库 泛型程序设计及STL的结构
随机推荐
- Delphi 函数的重载和作用域
1.在delphi 中,我们可以使用相同的函数名来调用不同的函数,我们称这个函数为重载,函数的参数类型和参数的个数可以不同,用到的关键字overload:格式如下: function addInt(x ...
- 统计apachelog各访问状态个数(使用MapReduce)
统计日志文件中各访问状态的个数. 1.将日志数据上传到hdfs 路径 /mapreduce/data/apachelog/in 中 内容如下 ::::::: - - [/Feb/::: +] :::: ...
- 012_流式计算系统(Mahout协同过滤)
课程介绍 课程内容 1.Mahout是什么 l Mahout是一个算法库,集成了很多算法. l Apache Mahout 是 Apache Software Foundation(ASF)旗下的 ...
- Codeforces 351B Jeff and Furik:概率 + 逆序对【结论题 or dp】
题目链接:http://codeforces.com/problemset/problem/351/B 题意: 给你一个1到n的排列a[i]. Jeff和Furik轮流操作,Jeff先手. Jeff每 ...
- R语言编程中的常见错误
R语言编程中的常见错误有一些错误是R的初学者和经验丰富的R程序员都可能常犯的.如果程序出错了,请检查以下几方面. 使用了错误的大小写.help().Help()和HELP()是三个不同的函数(只有第 ...
- POJ 1270 Following Orders(拓扑排序)
题意: 给两行字符串,第一行为一组变量,第二行时一组约束(每个约束包含两个变量,x y 表示 x <y).输出满足约束的所有字符串序列. 思路:拓扑排序 + 深度优先搜索(DFS算法) 课本代码 ...
- 实现html表头固定,表格内的信息向上滚动
效果如下: <!doctype html>Table header header two fuck 1 fuck 2 fuck 1 fuck 2 fuck 1 fuck 2 fuck 1 ...
- FileInputStream 原理总结 把文件作为字节流进行读操作
package io; import java.io.FileInputStream; import java.io.IOException; public class IOUtil { /** * ...
- BEC listen and translation exercise 38
很高兴看到有这么多人想了解我们的体育设施.It's good to see that there are so many people wanting to find out about our sp ...
- linux命令学习笔记(35):ln 命令
ln是linux中又一个非常重要命令,它的功能是为某一个文件在另外一个位置建立一个同步的链接.当我们需要在 不同的目录,用到相同的文件时,我们不需要在每一个需要的目录下都放一个必须相同的文件,我们只要 ...