STL与泛型编程<八>:迭代器简介

总述

迭代器是一种型别(通俗的讲就是以一种类)声明如下

template <class Category,              // iterator::iterator_category
          class T,                     // iterator::value_type
          class Distance = ptrdiff_t,  // iterator::difference_type
          class Pointer = T*,          // iterator::pointer
          class Reference = T&         // iterator::reference
          > class iterator;

所有容器都定义其各自的迭代器型别(iterator types),所以不需要专门的头文件,但有的迭代器需要,如逆向迭代器,被定义在#include中,迭代器是一种“能够遍历某个序列内所有元素”的对象,它可以透过一般指针一致的接口来完成自己的工作。其主要分为以下几种,见图
这里写图片描述

input(输入)迭代器

input迭代器只能一次一个向前读取元素,按顺序一个个传回元素值。注意input迭代器只能读取元素一次,如果你复制了input迭代器,并使原input迭代器和新产生的副本都向前读取,可能会遍历到不同的值
几乎所有的迭代器都具有input迭代器的功能,一个典型的例子就是从“标准输入读取数据”,同一个值不会被读两次。常见操作见下图
这里写图片描述
注意input迭代器不提供递减运算操作符

output(输出)迭代器

output迭代器是将元素值一个个写入,也就是说,你只能一个个元素地赋新值,而且不能使用output迭代器对同一序列进行两次遍历,下图是其操作
这里写图片描述
operator/*只有在赋值语句左手边才有效,注意output迭代器无需比较,无法检验output迭代器是否写入成功,唯一可以做的就是写入,再写入,几乎所有迭代器都具有output迭代器的功能。一个典型的例子“将元素输出到标准输出设备”的迭代器;output迭代器另一个典型例子就是inserters,所谓inserters是用来将元素插入容器的一种迭代器。

forward(前向)迭代器

forward迭代器是input迭代器和output迭代器的结合,具有input迭代器的全部功能和output迭代器的部分功能,其操作如下图
这里写图片描述
为什么具有output迭代器的部分功能,见下
若是output迭代器,我们无需检查是否抵达序列尾端,便可直接写入数据,因此可以这样写

while (true)
{
    *pos = foo();
    ++pos;
}

对于forward迭代器,必须在存取数据之前确保有效,否则会引发未定义的行为,因此得这么写

while (pos != col.end())
{
    *pos = foo();
    ++pos;
}

这个循环不适合output迭代器,因为output迭代器没有定义operator!=

bidirectional(双向)迭代器

双向迭代器在forward迭代器的基础上提供了回头遍历的能力,换言之,它支持递减运算符,其新增操作如下
这里写图片描述
- random access(随机存取)迭代器
random access迭代器在双向迭代器的基础上再增加随机存取能力,因此它必须提供“迭代器算术运算”,也就是说它能够加减某个偏移量,能处理距离问题,并运用比较操作符,以下迭代器支持rand access迭代器:
1. 可随机存取的迭代器(vector,deque)
2. string(字符串,string,wstring)
3. 一般array(指针)
其新增的操作如下图
这里写图片描述
见一个例子

#include <iostream>
#include <vector>
using namespace std;

int main(void)
{
    vector<int> col;
    for (int i=-3; i<=9; ++i)
        col.push_back(i);
    //只适用于随机迭代器
    cout << "number/distance: " << col.end() - col.begin() << endl;

    vector<int>::iterator pos;
    for (pos=col.begin(); pos!=col.end(); ++pos)
        cout << *pos << ' ';
    cout << endl;

    //此操作只对random access 有效
    for (int i=0; i<col.size(); ++i)
        cout << col.begin()[i] << ' ';
    cout << endl;

    //此操作只对random access 有效
    for (pos=col.begin(); pos < col.end()-1; pos+=2)  //注意这里的循环结束条件(避免未定义行为)
        cout << *pos << ' ';
    cout << endl;

    return 0;
 } 

本例对lists,sets和maps无效,因为程序中标识的部分都只适用于random access迭代器。注意只有在面对random access迭代器时,才能以operator< 作为结束与否的判断准则
对于程序中最后一个循环的解释见下图
这里写图片描述

容器的迭代器类型

  1. vector和deque的迭代器是随机迭代器,灵活性最大,基本适用于任何一个STL算法及迭代器相关操作
  2. list的迭代器是双向迭代器,因此凡是用到随机迭代器的STL算法你都不能使用
  3. set和map的迭代器也是双向迭代器
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值