C++PrimerPlus(第6版)中文版:Chapter16.4泛型编程_为何使用迭代器_迭代器类型

本章节的上一个程序是vect3.cpp(目前还没有实践过,会在以后去实现)

STL 是一种泛型编程(generic programming),面向对象编程关注的是编程的数据方面,而泛型编程关注的是算法。他们的共同点是抽象和创建可以重复使用的代码,但是理念决然不同。

泛型编程旨在编写独立于数据类型的代码。

16.4.1为何使用迭代器

理解迭代器是理解STL的关键。模版使得算法独立于存储的数据类型,而迭代器使算法独立于使用的容器类型,因此他们都是STL通用方法的重要组成部分。

泛型编程旨在使用同一个find 函数来处理数组、链表、或其他的数据类型。即函数不仅独立于容器中存储的数据类型,还独立于容器本身(就是说啥容器来了都可以使用)。模版提供了存储在容器中数据类型的通用表示,因此还需要遍历容器中的值的通用表示,而迭代器就是这样的通用表示。

迭代器应该具备哪些特征呢?

  • 应该能对迭代器进行解除引用的操作,以便能够访问它所引用的值,p是迭代器,则应该对*p进行定义。(我已经理解该条,迭代器,解引用,就能够访问到值了)
  • 应该能够将一个迭代器赋给另外一个。p和q都是迭代器,那么应该对p=q进行定义。(不是很理解该条)
  • 应该能够将一个迭代器与另外一个比较,看看他们是否相等。对p==q,p!=q进行定义。(不是很理解该条)
  • 应该用迭代器去遍历容器中的元素,这可以通过定义++p,p++来实现。(我已经理解该条,迭代器吗,就是该做遍历的事情,++ 就是往下一个目标走的意思呗。)

STL按功能强弱定义了多种级别的迭代器。 常规指针就能满足迭代器的要求。

可以定义一个迭代器类,定义了运算符* 和 ++

struct Node
{
	double item;
	Node* p_next;
};
class  iterator
{
	Node* pt;

public:
	iterator() :pt(0) {};
	iterator(Node* pn) :pt(pn) {}
	double operator *() { return pt->item; }
	iterator& operator++()//for ++it
	{
		pt = pt->p_next;
		return *this;
	}
	iterator& operator++(int)//for it++
	{
		iterator tmp = *this;
		pt = pt->p_next;
		return tmp;
	}
	//operator ==(),operator!=() ,etc 
	~ iterator();

private:

};

这里,具体的iterator类的写法并不重要,重要的是,有了迭代器类之后,书中的第二个find函数(即在链表中find)可以这样来写了

iterator find_ll(iterator head, const double& val)
{
	iterator start;
	for (start = head;start!= 0; ++start)
		if (*start == val)
			return start;
	return 0;
}

而这种写法就和find_ar()几乎相同了。

STL 遵循了上面介绍的方法。

首先,每个容器类定义了相应的迭代器类型,对于其中的某个类,迭代器可能是指针,而对于另外的类,迭代器可能是对象。

其次,每个容器都有一个超尾标记,当迭代器递增到超越容器的最后一个值后,这个值将赋给迭代器。每个容器类都有begin() 和end()方法,它们分别返回一个指向容器的第一个元素和超尾位置的迭代器。每个迭代器都使用++操作,让迭代器从指向第一个元素逐步指向超尾位置,从而遍历容器中的每一个元素。

使用容器类的时候,无需知道其迭代器是如何实现的,也无需知道超尾是如何实现的,只需要知道begin()返回一个指向第一个元素的迭代器,end()返回一个指向超尾位置的迭代器即可。

16.4.2迭代器类型

STL定义了5种迭代器,并根据所需要的迭代器类型对算法进行了描述。5种分别是:输入迭代器、输出迭代器、正向迭代器、双向迭代器、随机访问迭代器。

1输入迭代器:输入是从程序的角度来说的,即来自与容器的信息被视为输入,输入迭代器可被程序用来读取容器中的信息。具体地说对输入迭代器解除引用将使程序能够读取容器中的值,但不一定能让程序修改值。因此需要输入迭代器的算法将不会修改容器中的值。基于输入迭代器的任何算法,都应当是单同行的(single-pass),不依赖于前一次遍历时的迭代器值,也不依赖本次遍历中前面的遍历值。

输入迭代器是单向迭代器,可以递增,但不能倒退。

2输出迭代器:输出是指将信息从程序传输给容器的迭代器,程序的输出就是容器的输入。输出迭代器和输入迭代器类似,只是解除引用让程序能够修改容器值,而不能读取。(例如发送给显示器上的输出就是如此,cout可以修改发送给显示器的字符流,但是却不能读取屏幕上的内容。)

对于单通行、只读算法,可使用输入迭代器;而对单通行、只写算法,则可以使用输出迭代器

3正向迭代器:正向迭代器只使用++运算符来遍历容器,所以它每次沿容器向前移动一个元素,与输入、输出迭代器不同的是,它总是按相同的顺序遍历一系列值。另外,将正向迭代器递增后,仍然可以对前面的迭代器解除引用,并可以得到相同的值,这些特征使得多次通行算法成为可能

正向迭代器可以读取和修改数据,也可以只能读取数据。

int * pirw//read-write iterator     读写迭代器

const int * pir//read-only iterator 只读迭代器

4双向迭代器:假设算法需要双向遍历容器,例如:reverse函数可以交换第一个元素和最后一个元素,将指向第一个元素的指针加1,将指向最后一个元素的指针减1,并重复这种处理过程。双向迭代器具有正向迭代器的所有特征,同时支持两种(前缀和后缀)递减运算符。(说白了就是定一个了operator--呗)。

5随机访问迭代器:有些算法(例如标注排序和二分检索)需要能够直接跳到容器中的任何一个元素,这就叫做随机访问。这就需要随机访问迭代器。随机访问迭代器具有双向迭代器的所有特性,同时添加了支持随机访问的操作(如指针增加运算)和用于对元素进行排序的关系运算符

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值