初识C++ · 反向迭代器简介

目录

前言

反向迭代器的实现


前言

继模拟实现了list和vector之后,我们对迭代器的印象也是加深了许多,但是我们实现的都是正向迭代器,还没有实现反向迭代器,那么为什么迟迟不实现呢?因为难吗?实际上还好。

我们实现const迭代器的时候,有两种路,一是直接来一个类,二是通过模板,非const迭代器的复用来实现的,同理,我们实现反向迭代器的话,也可以每种结构都来一个单独的反向迭代器的类,但是科学家们觉得太麻烦了,所以把反向迭代器的高度拉的很高,高到什么程度呢?高到一个反向迭代器可以适配所有的结构,本质上就是复用原来的正向迭代器,两种迭代器的区别只是遍历的方向不同而已,即++变成--,源码的实现方式比较复杂,我们实现方式是,传正向迭代器过来,复用对应正向迭代器的函数即可,这里就需要单独创建一个类模板了。


反向迭代器的实现

我们大思路是通过判断传的迭代器的不同,调用对应正向迭代器的函数,所以我们创建的反向迭代器的类的成员变量是iterator,实现的接口还是那么几个,!= * -> ++ -- :

cpp 复制代码
namespace Free
{
	template <class iterator,class Ref,class Ptr>
	struct ReverseIterator
	{
		typedef ReverseIterator<iterator,Ref, Ptr> self;
		ReverseIterator(iterator it)
			:_it(it)
		{}

		iterator _it;
	};
}

迭代器其实有个共同的特点就是一般使用struct,因为里面的变量函数什么的都是要访问的,使用class就麻烦了一点点。

第一个参数是迭代器,也就是判断复用谁的迭代器,第二个参数是引用,第三个参数是指针类型。

这里需要引入一个问题

这是我们没真正接触反向迭代器之前所猜想的反向迭代器结构。

但是源码的操作不是的,计算机科学家们可能有点强迫症?希望对称。

这是链表中的反向迭代器,顺序表同理,主打的就是一个对称。

那么这时候的访问就成了问题,此时源码的神之一手出现了,比如链表,rbegin第一次访问的结果应该是5,那么我们就来一个临时变量,++之后(实际上是--)访问到5即可,这里是不可以迭代器-1或者迭代器--的,因为迭代器本身我们不能破坏,但是临时变量却可以随意捣鼓。

cpp 复制代码
template <class iterator,class Ref,class Ptr>
struct ReverseIterator
{
	typedef ReverseIterator<iterator,Ref, Ptr> self;
	ReverseIterator(iterator it)
		:_it(it)
	{}

	Ref operator*()
	{
		iterator tmp = _it;
		return *(--tmp);
	}

	Ptr operator->()
	{
		return &(operator*());
	}

	self& operator++()
	{
		--_it;
		return *this;
	}

	self& operator--()
	{
		++_it;
		return *this;
	}

	bool operator!=(const self& s)
	{
		return _it != s._it;
	}

	iterator _it;
};

这样的一个反向迭代器就算是完成了。


list vector中反向迭代器的应用

注意,这里实现的反向迭代器是个简单版本,只适用于list和vector。

使用的话,加几个typedef 来几个reverse_iterator函数就没问题了,比如list:

cpp 复制代码
template<class T>
class list
{
public:
	typedef ListNode<T> Node;
	typedef ListIterator<T,T&,T*> iterator;
	typedef ListIterator<T,const T&,const T*> const_iterator;
	typedef ReverseIterator<iterator,T&,T*> reverse_iterator;
	typedef ReverseIterator<const_iterator,const T&,const T*> const_reverse_iterator;
	reverse_iterator rbegin()
	{
		return reverse_iterator(end());
	}
	reverse_iterator rend()
	{
		return reverse_iterator(begin());
	}
}

依旧不要忘记反向迭代器的核心是复用正向迭代器的函数,第一个参数一定是迭代器。

vector:

cpp 复制代码
class vector
{
public:
	typedef T* iterator;
	typedef const T* const_iterator;

	typedef ReverseIterator<iterator, T&, T*> reverse_iterator;
	typedef ReverseIterator<const_iterator, const T&, const T*> const_reverse_iterator;

	reverse_iterator rbegin()
	{
		return reverse_iterator(end());
	}
	reverse_iterator rend()
	{
		return reverse_iterator(begin());
	}
}

测试代码:

cpp 复制代码
int main()
{
	Free::list<int> lt = { 1,2,3,4 };
	Free::list<int>::reverse_iterator rit = lt.rbegin();
	while (rit != lt.rend())
	{
		cout << *rit << " ";
		++rit;
	}
	cout << endl;
	Free::vector<int> v = { 1,2,3,4 };
	Free::vector<int>::reverse_iterator it = v.rbegin();
	while (it != v.rend())
	{
		cout << *it << " ";
		++it;
	}
	return 0;
}

注意前置++和后置++的使用。


感谢阅读!

相关推荐
MetaLite7 小时前
Java 时间处理的两个坑:单位误判,半秒算成一秒
java·开发语言·前端
汉克老师7 小时前
GESP 六级明日冲刺:最后一晚只抓两个大方向
c++·gesp·小学生·学c++编程
萧鼎8 小时前
Python 数据验证神器 Pydantic:数据解析与验证、设置管理、JSONSche、与ORM集成全搞定
开发语言·python
神仙别闹8 小时前
基于 QT(C++)开发的地铁换乘系统
数据库·c++·qt
haon11228 小时前
海外信贷的策略全生命周期:从准入到还款的本地化布防
大数据·开发语言·深度学习·面试·职场和发展·产品经理
linx2958 小时前
单元四 · 对称认知·上:内存与指针
c语言·开发语言·数据结构·嵌入式硬件·算法
529宝宝起名网8 小时前
用 Python 开发名字字源查询工具:从甲骨文到楷书的字形演变与文化寓意解析
开发语言·python
白远山8 小时前
家政服务派单平台搭建实战指南:从需求分析到系统设计全流程解析
java·开发语言·架构·uni-app·需求分析
Dr_Fourier9 小时前
mmap的使用与底层原理
linux·c++
Tairitsu_H9 小时前
[C++] C++11右值引用与移动语义揭秘
开发语言·c++·c++11·右值引用·移动语义