C++学习笔记:迭代器

原创 2012年03月30日 15:39:19

迭代器提供按元素逐个访问一个序列的方法。序列的内容可以是数值、字符或几乎任何类型的对象。标准容器(如向量)提供访问容器内容的迭代器,有的标准迭代器还允许访问输入流与输出流。标准算法仅使用迭代器操作序列。

C++有五类不同的迭代器:输入迭代器、输出迭代器、前向迭代器、双向迭代器、随机访问迭代器。输入、输出迭代器功能最少,随机访问迭代器功能最多。在任何使用功能少的迭代器的地方均可以利用功能多的迭代器替代。几种迭代器的主要功能:

输入迭代器:输入迭代器只支持输入。这种迭代器的每次迭代只能执行一次读操作(通过单目*操作符),不能修改迭代器引用的数据项。++操作符可以递增到下一个输入数据项。可以对这种迭代器比较相等性与不等性,但只有将一个迭代器与末端迭代器进行比较才是有意义的。通常情况下不能通过比较两个输入迭代器来判定它们是否引用相同的数据项。

输出迭代器:输出迭代器只支持输出。可以向这种迭代器赋予一个数据项(通过对赋值表达式左边的迭代器使用*操作符),但不能从迭代器读取数据。每次迭代只能修改一次迭代器的值,++操作符可将其递增到下一输出数据项。

不能对输出迭代器比较相等性与不等性。

另外,在处理输出迭代器是要注意:必须确保迭代器真实写入的地方有足够的空间存储输出数据整体,任何错误都将导致不确定的行为。

前向迭代器:前向迭代器出具有输入输出迭代器的全部功能外,还有更多功能。可以自由的读写一个迭代器的数据项,并且可以随意的操作任意多次。++操作符可以递增到下一数据项。==与!=操作符用于比较迭代器,检测它们是否引用相同的数据项或是否达到末端。

双向迭代器:双向迭代器不仅具有前向迭代器的所有功能,而且支持--操作符,这可以是迭代器移回到之前所在的数据项。与任何迭代器一样,需要确保迭代器不超过区间末尾,也不引用到区间起始之前。

随机访问迭代器:随机访问迭代器是最强大的迭代器,它具有其他所有迭代器的所有功能,此外还可以通过加上或减去整数的方式使迭代器移动任意量。

const_iterator与const iterator

如果你需要对区间内的数据只读,而所用的迭代器可能是前向迭代器,双向迭代器或随机访问迭代器,你可能真正需要的仅是一个输入迭代器。你也许认为将迭代器声明为const会有用,那么看下面的程序:

#include <iostream>
#include <ostream>

#include "data.hpp"

int main()
{
  intvector data;
  read_data(data);
  const intvec_iterator iter(data.begin());
  std::advance(iter, data.size() / 2); // move to middle of vector
  if (not data.empty())
    std::cout << "middle item = " << *iter << '\n';
}

=================================================

data.hpp:

#ifndef DATA_HPP_
#define DATA_HPP_

#include <algorithm>
#include <iostream>
#include <iterator>
#include <ostream>
#include <vector>

typedef std::vector<int> intvector;
typedef intvector::iterator intvec_iterator;

template<class Container>
void read_data(Container& data)
{
  data.clear();
  data.insert(data.begin(), std::istream_iterator<typename Container::value_type>(std::cin),
              std::istream_iterator<typename Container::value_type>());
}

template<class Container>
void write_data(Container const& data)
{
  std::cout << "{ ";
  std::copy(data.begin(), data.end(),
            std::ostream_iterator<typename Container::value_type>(std::cout, " "));
  std::cout << "}\n";
}
#endif

编译器会拒绝编译该程序,原因在于iter是const的。你不能修改这个迭代器,因此不能将其移动到向量中间。不能将迭代器本身声明为const,而需要告编译器你希望迭代器引用const数据。如果向量本身是const的,其begin()函数将返回这样一种迭代器;可以自由的修改迭代器的位置,但不能修改迭代器引用的值。这种函数返回的迭代器名字是const_iterator。

所以要想使上面的程序成功编译,则只需将const intvec_iterator iter(data.begin());修改为intvector::const_iterator iter(data.begin());


C++中的#,##,和"

想要灵活应用宏,离不开#和##。 " 在学习#和##之前,先来看一个关于"的例子: #include #include int main() { const char* p1 = ...
  • mzlogin
  • mzlogin
  • 2014年11月09日 22:47
  • 7591

C++中的::的作用

(1)作用域限定符,当在类体中直接定义函数时,不需要在函数名字的前面加上类名,但是在类体外实现函数定义的时候,必须加上类名并且加上作用域限定符。Student::Display(); (2)...
  • zhanghuaichao
  • zhanghuaichao
  • 2017年02月18日 21:44
  • 2259

浅论C++的复杂性

C++语言已经有了20多年的历史。作为一门影响广泛的编程语言,它所受到的关注和争论恐怕是任何一门其他的语言所不能比拟的。十几年前,Java等新生语言的出现曾导致“C++信任危机”,但最终C++以自身非...
  • K346K346
  • K346K346
  • 2015年12月05日 11:56
  • 1738

c/c++中指针的理解(初学者)

关于指针,大家肯定不陌生,一些初学者,想必会出现思绪混乱的情况,现在我就来帮大家缕一缕吧。(第一次写微博 有点小紧张) 大家应该了解一些计算机对内存的管理方式吧。操作系统会将内存单元进行编号,这些...
  • Allen_ww
  • Allen_ww
  • 2016年01月11日 19:41
  • 8788

没事写点啥(一)——C++扫雷

整天编学校的作业实在枯燥,不如……写点别的?
  • destinyson
  • destinyson
  • 2016年02月29日 14:17
  • 1762

C++笔试题目大全(笔试宝典)(不断完善中)

1.new 、 delete 、 malloc 、 free 关系 delete 会调用对象的析构函数 , 和 new 对应 free 只会释放内存, new 调用构造函数。 malloc 与 f...
  • Lina_ACM
  • Lina_ACM
  • 2016年06月07日 13:29
  • 21419

C/C++中“#”和“##”的作用和用法

C/C++中“#”和“##”的作用和用法!
  • fengbingchun
  • fengbingchun
  • 2015年03月08日 16:15
  • 3385

C++ 进程间的通讯(一):简单的有名管道实现

进程间的通讯(一):简单的有名管道实现 一 管道简介 命名管道(Named Pipe)是服务器进程和一个或多个客户进程之间通信的单向或双向管道。不同于匿名管道的是命名管道可以在不相关的进程...
  • u010797208
  • u010797208
  • 2014年11月28日 02:09
  • 6576

OpenCV中Mat的C++用法介绍

Mat       OpenCV 自 2001 年出现以来。在那些日子里库是围绕C接口构建的。在那些日子里,他们使用名为IplImage C 的结构在内存中存储图像。这是您将在大多数较旧的教程和...
  • wadefan7
  • wadefan7
  • 2015年03月05日 15:53
  • 4295

关于C和C++一些大神们的讨论

知乎上曾经有一个关于C和C++语言的讨论,弄的沸沸扬扬。余天升 开源社区一直都不怎么待见C++,自由软件基金会创始人Richard Stallman认为C++有语法歧义,这样子没有必要、非常琐碎还会...
  • wangshubo1989
  • wangshubo1989
  • 2016年02月23日 20:33
  • 2637
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++学习笔记:迭代器
举报原因:
原因补充:

(最多只允许输入30个字)