<C++> 反向迭代器

一、反向迭代器构造方式

1. 正向迭代器

        我们知道正向迭代器的设计:begin迭代器指向第一个数据,end迭代器指向最后一个数据的下一个位置 。

        迭代器++,移向下一个数据,解引用得到数据的值。

        根据容器储存方式的不同,容器有不同类型的迭代器。

2. 反向迭代器

        注意:rbegin迭代器指向最后一个数据的下一个位置,rend迭代器指向第一个数据,这里就体现了镜像对称,正向与反向迭代器成为对称关系。

        可是,如果按照rebegin指向的位置,第一次解引用得到的应该是随机值,这是有问题的,那么stl解决方案是什么呢?它采用的方法是:解引用得到的是rebegin迭代器前一个位置的数据

        为了简便,反向迭代器采用的是适配器模式,适配正向迭代器反向迭代器的++将调用正向迭代器的--,反之亦然。

例如:

二、反向迭代器模板 

         我们给出统一的反向迭代器模板,对于各容器,由模板实现各自的迭代器。给模板什么正向迭代器,它就适配出相应容器的反向迭代器

#pragma once
namespace my_ReverseIterator
{
	template<class Iterator, class Ref, class Ptr>
	struct ReverseIterator
	{
		typedef ReverseIterator<Iterator, Ref, Ptr> self;
		Iterator _it;

		ReverseIterator(Iterator it)
			:_it(it)
		{}

		Ref operator*()
		{
			Iterator tmp = _it;
			return *(--tmp);	//这里没有模板类型,该返回什么类型呢?1. 萃取 2. 使用者在模板处给出
		}

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

			//还可以写成
			//Iterator tmp = _it;
			//return &(*--tmp);
		}

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

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

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

成员变量

  • 反向迭代器采用适配器模式将iterator类型变量作为反向迭代器类的成员变量(同stack、queue、priotiry_queue的构造方法一样)
  • 后两个模板类型与Iterator模板类型相同,用于不同权限的返回值,
  • Ref:T& 或 const T& 
  • Ptr: T*  或 const T*
#pragma once

namespace my_ReverseIterator
{
	template<class Iterator, class Ref, class Ptr>
	struct ReverseIterator
	{
		typedef ReserveIterator<Iterator, Ref, Ptr> self;
        
        //成员变量
		Iterator _it;
	};
}

operator*

  • 根据STL的构造,返回--后迭代器指向的数据
  • *(--tmp)实际上是调用了iterator类内部的operator*()函数,返回迭代器指向的数据的值
		Ref operator*() 
		{
			Iterator tmp = _it;
			return *(--tmp);	//这里没有模板类型,该返回什么类型呢?1. 萃取 2. 使用者在模板处给出
		}

operator->

  •  同Iterator的operator->()设计思想,该函数是为了防止数据类型不是单一数据,可能是类或结构体,含有多数据时只有解引用是不够用的,是错误的
  • 可以返回 &(operator*())   也可返回 &(*--_tmp)&(*--_tmp)表示的是:--tmp后,先调用tmp的operator*()函数,得到数据的值(可能是结构体,即自定义类型,也可能是单一的数据,即内置类型),再取地址即可
		Ptr operator->()
		{
            //Iterator tmp = _it;
            //return &(*--tmp);
			return &(operator*());
		}

operator++ && operator--

  • 前置的++或-- 
  • 返回引用,是因为*this表示的是反向迭代器这个类实例化的对象,它的生命周期是不在该operator++或--类内部的,所以可以返回引用
		self& operator++()
		{
			--_it;
			return *this;
		}

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

operator!=

  • 反向迭代器的比较,比较低是成员变量iterator,比较iterator时,又会转换为iterator重载的operator!=函数
  • 形参const修饰反向迭代器,常引用权限,外部的const是修饰 *this,表示不可修改this指针里的内容
		bool operator!=(const self& s) const
		{
			return _it != s._it;
		}

三、补充之前模拟实现的容器反向迭代器设计

我们补充上list、vector容器的迭代器

1. list

要将ReverseIterator头文件展开在list模拟实现的文件中,并展开命名空间域,这样编译器才会识别ReverseIterator这个类型

		typedef __list_iterator<T, T&, T*> iterator;	//迭代器要公有,让外面可以使用
		typedef __list_iterator<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;

		//用 end 适配 rbegin
		reverse_iterator rbegin()
		{
			return reverse_iterator(end());
		}

		//用 begin 适配 rend
		reverse_iterator rend()
		{
			return reverse_iterator(begin());
		}

		iterator begin()
		{
			//由指针类型隐式转换为iterator类
			//return _head->_next;

			//也可以用匿名对象
			return iterator(_head->_next);
		}

		iterator end()
		{
			return iterator(_head);
		}

2. vector

		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());
		}

		iterator begin()
		{
			return _start;
		}

		iterator end()
		{
			return _finish;
		}

        其余容器也相同,读者可自行添加


总结:        

        反向迭代器也是适配器模式,这是重点,使用 end() 适配 rbegin(),begin() 适配 rend()。

        我们搞清楚,这些类之间的关系,简单的一个*或!=它的背后都可能是运算符重载,简单的=可能是调用默认生成的赋值运算符重载而实现的


        最后,如果小帅的本文哪里有错误,还请大家指出,请在评论区留言(ps:抱大佬的腿),新手创作,实属不易,如果满意,还请给个免费的赞,三连也不是不可以(流口水幻想)嘿!那我们下期再见喽,拜拜!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值