五、迭代器--迭代器类型详述

来源:互联网 发布:java数组的定义格式 编辑:程序博客网 时间:2024/06/08 14:16

五、迭代器

标签(空格分隔): c++STL


1. 迭代器及其特性

  1. 迭代器本身就是一种对象
  2. 迭代器不是通用指针,而是指向数组的指针概念的抽象
  3. 迭代器就是一个指示器
  4. 迭代器能够使程序反复得对stl容器内容进行访问,当参数化类型为c++内部类型的时候,迭代器是c++的指针。

每种容器都支持某种类别的迭代器,类别有:

  • 输入:为程序需要数据源提供接口,数据源可以是容器,数据流等,输入迭代器只能从一个序列读入数据,此类迭代器可以被修改,引用并进行比较。

  • 输出: 用于输出程序中得到的结果,输出迭代器只能向一个序列输出数据,此类迭代器可以被修改和引用。

  • 前向:可以随意访问序列中的元素,可以用来读,也可写。并能保存迭代器的值,以便重新从原先位置开始遍历。

  • 双向: 能够读写,也可被增值和减值,同时进行前向和逆向操作,所有stl都提供双向迭代器;

  • 随机访问: 可以通过跳跃的方式访问容器中的任意数据,访问数据灵活。具有双向迭代器所有功能,冰球能使用算法和所有迭代器的比较功能。

迭代器的关键属性:
- 当前被指向的元素: 用“*”或“->”表示:
- 指向下一个元素: 迭代器使用增量运算符:++``
- 相等,使用运算符
==`
- 只有随机迭代器可以通过加减整数,取得相对地址;
- 除了输出迭代器之外,可以获得任意两个迭代器的距离(使用distance函数)

2.头文件简述

所有的容器都定义其各自的迭代器,不需要包含专门的头文件。
但是,逆向迭代器包含在头文件<iterator>之中

1. 迭代器类型详述

  1. 迭代器是一种“能够遍历某个序列所有元素”的对象。
  2. 迭代器是抽象概念,只要行为类似迭代器,就是一种迭代器
    迭代器的层次结构为:
    A[Random access]-->B(Bidirectional)    B-->C[Forward]    C-->D[input]    C-->E[Output]

Input迭代器:用于向前读取
Output迭代器: 用于向前写入
Forward迭代器: 用于读取和写入;
Bidirectional迭代器: 双向迭代器用于前后读取写入;
Random access 迭代器: 随机存取 ,用于读取写入

1.输入型迭代器(InputIterator)

  1. 只能一次次地向前读取元素,并按照顺序传回元素值。
  2. 迭代器只能读取元素一次
  3. 如果两个输入型迭代器占用一个位置,则两者相同

输入型迭代器的操作:

  • * :从迭代器中读取元素值
  • -> :读取元素的成员
  • ++: 代表前向步进;最好使用前置递增,性能更好
  • ==: 判断相等
  • !=: 判断不等
  • TYPE(iter) : 赋值迭代器

2. 输出型迭代器(OutputIterator)

  1. 作用是将元素逐个写入。即只能逐个元素赋值。
  2. 不能使用输出型迭代器同一个序列进行两次遍历
  3. 输出型可以实现的操作有: *,++和复制操作

例子:
1. “将元素写至标准输出装置”的迭代器,如果采用两个输出型迭代器,第二个字将跟在第一个字的后面,而不是覆盖;

  1. “插入器(inserter)”

3. 前向迭代器

前向迭代器是输入型和输出型迭代器的组合。
前向迭代器的操作;

表达式 效果 *Iter 取实际元素 Iter->number 存取实际元素的成员 ++Iter 向前步进 Iter++ 向前步进 Iter == Iter2 判断两个迭代器相等 Iter1 != Iter2 判断两个迭代器不等 TYPE() 产生迭代器(默认构造函数) TYPE(Iter) 复制迭代器 Iter1=Iter2 赋值

前向迭代器能多次指向同一集合的同一元素,并能多次处理同一元素;
- Output迭代器: 无需检查是否抵达尾端,可直接写入数据。不提供比较操作,不能讲Output迭代器和尾端迭代器比较。
- Forward迭代器: 在使用之前,需要确保迭代器是否有效! 在使用的时候,尽量使用begin()和end()作为循环的起始。

4.双向迭代器

双向迭代器在前向迭代器的基础上增加了回头遍历的功能。可以支持递减运算符。
新增操作:

表达式 效果 –Iter / Iter– 步退

5.随机存取迭代器

在双向迭代器的基础上增加了随机存取能力。
因此,必须增加迭代器运算操作。即可以实现迭代器加减某个偏移量,能处理距离问题,并可运用<>等关系运算符操作。
可以支持随机存取迭代器的容器对象或数据类型有:
- vector
- deque
- strings(string,wstring)两个string类型
- array 普通数组

随机迭代器的各项操作

表达式 效果 Iter[n] 存取索引位置为n的元素 Iter+=n 前进n个元素 Iter-=n 后退n 个元素 Iter+n / n+Iter 传回iter之后的第n个元素 Iter-n 传回iter之前的第n个元素 Iter1 - Iter2 判断Iter1和Iter2的距离 Iter1 < Iter2 判断iter1是否在iter2之前 Iter1 > Iter2 判断iter1 是否在iter2 之后 Iter1 <= Iter2 判断iter1是否不在iter2之后 Iter1 >= Iter2 判断iter1是否不再iter2之前

【注: 】随机存取迭代器对 listsets还有maps是无效的。

6.vector迭代器的递增和递减

一般可以递增或递减暂时性容器,但是对弈vector和string容器不同;
如:

vector<int> v;if(v.size() >1) {sort(++v.begin(),v.end());}

上述代码在编译的时候会出错,换成deque,就能通过编译。
原因:
1. vector 迭代器在实际操作中通常作为一般指针。c++不允许修改任何基本类型的暂时值;对于struct和class则可以;
2. 如果迭代器被实例化一般指针,编译会失败;如果迭代器被实例化class,则编译成功。deque,lists,sets和maps总能通过编译,因为这些容器的迭代器不可能被实例化为一般指针;

本内容摘抄自《c++标准程序库开发指南–不要重复造轮子》第二版
实验了一下,我在vs2013编译通过,没有出现这个问题,记录一下:不懂其中的原理。

//vs 2013vector<int> vec2 = {9,3,3,5,2,3,1,6,7};if (vec2.size() >1) {    sort(++vec2.begin(), vec2.end());}--------------省略----------------

结果为;

size: 9vec2: 9   1   2   3   3   3   5   6   7
原创粉丝点击