【迭代器】迭代器相应型别


迭代器相应类型有五种, iterator_traits类专门用来“萃取”迭代器的特性。

下面的代码中,IT表示的是任意迭代器的类型。

泛化版本:

template <class I>
struct iterator_traits {
	typedef typename I::value_type value_type;
	typedef typename I::difference_type difference_type;
	typedef typename I::reference reference;
	typedef typename I::pointer pointer;
	typedef typename I::iterator_category iterator_category;
};

型别必须加上关键词typename,因为I是一个模板参数,在它被编译器具现化之前,编译器对I一无所知,并不知道I::value_type是型别还是成员函数还是成员数据。

针对原生指针而设计的特化版本:

template <class T>
struct iterator_traits<T*> {
	typedef T value_type;
	typedef ptrdiff_t difference_type;
	typedef T &reference;
	typedef T *pointer;
	typedef random_access_iterator_tag iterator_category;
};
template <class T>
struct iterator_traits<const T*> {
	typedef T value_type;
	typedef ptrdiff_t difference_type;
	typedef const T& reference;
	typedef const T *pointer;
	typedef random_access_iterator_tag iterator_category;
};

如果你希望你开发的容器能与STL交互,一定要为你的容器的迭代器定义这五种类型。

value_type

value_type是指迭代器所指对象的型别。

difference_type

difference_type表示两个迭代器之间的距离,它也可以表示一个连续容器的最大容量。如STLcount()

template <class I, class T>
typename iterator_traits<I>::difference_type count(I first, I last, const T &value)
{
	typename iterator_traits<I>::difference_type n = 0;
	while (first != last) {
		++n;
		++first;
	}
	return n;
}

对原生指针而言,使用ptrdiff_t作为其difference_type类型。

reference_type

迭代器可分为两种:不允许改变所指对象的是const iterator允许改变所指对象的是mutable iterator

C++中可以通过reference传值。

如果某个迭代器pvalue_typeT
(1) pconst iterator*p得到的是右值,类型为const T&
(2) pmutable iterator*p得到的是左值,类型为T&

pointer_type

pointerreferenceC++中有非常密切的关联。我们可以传一个引用,令它代表所迭代器所指之物;也可以传一个值,令它代表所指之物的地址。

iterator_category

根据移动特性和实施操作,迭代器被分为五类:
(1) InputIterator只读迭代器。
(2) OutputIterator只写迭代器。
(3) ForwardIterator单向移动迭代器,支持++操作。
(4) BidirectionalIterator双向移动迭代器,支持++--操作。
(5) RandomAccessIterator随机访问迭代器,支持++--+=-=<等操作。

以上五种迭代器的分类和从属关系,如下图所示:
在这里插入图片描述

直线与箭头代表的不是继承关系,而是concept(概念)与refinement(强化)的关系。顺着箭头的方向,强化的程度越高。

在这里插入图片描述
在这里插入图片描述
下面定义五个类,代表五种迭代器类型:

struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag : public input_iterator_tag {};
struct bidirectional_iterator_tag : public forward_iterator_tag {};
struct random_access_iterator_tag : public bidirectional_iterator_tag {};

这些类只作为标记,所以不需要任何成员。
运用继承机制是为了传递调用:如果没有匹配函数实参的形参类型,就去匹配实参类型的基类

任何一个迭代器,其类型落在“该迭代器所隶属之各类型中,最强化的那个”。比如int*,它既是RandomAccessIterator,也是BidirectionalIteratorForwardIteratorInputIterator,那么它的类型应该归属为RandomAccessIterator

STL算法的命名规则是:以算法所能接受之最低阶迭代器类型,来为迭代器型别参数命名。

总结

  1. 设计适当的相应型别(5种)是迭代器的责任。
  2. 设计适当的迭代器容器的责任。唯有容器本身才知道怎样的迭代器能遍历自己,并执行前进后退取值取用成员等操作。
  3. 算法和容器独立开发,以迭代器作为两者的粘合剂。
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值