【C++】反向迭代器

目录

一、反向迭代器介绍

二、实现反向迭代器

总结


前言

前面我们已经实现了很多的容器,但是我们都没有来实现反向迭代器,下面我们来模拟实现一个简单的反向迭代器


一、反向迭代器介绍

C++一共有4种迭代器,我们只剩下了反向迭代器,反向迭代器的使用与其它迭代器的使用并没有什么不同,与正向迭代器进行对比,正向迭代器++是向容器的下一个元素移动,而反向迭代器的++是向前一个元素移动,反向迭代器的很多行为与正向迭代器是相反的,由此我们也就清楚了,反向迭代器的思路。

二、实现反向迭代器

我们知道对于不同的容器他们的迭代器的功能是类似的,以list举例,我们要实现它的反向迭代器只要修改正向迭代器,实现出一份反向迭代器就好了,而对于vector同理。

但是这种做法具有很多重复代码,并且十分的占用内存,我们前面实现了容器适配器,所以我们可以仿照容器适配器,来实现一个反向迭代器。

我们可以使用正向迭代器来构造,反向迭代器的++就是正向迭代器的--,然后其它成员函数类似

我们可以看一下库中是如何实现的,从而验证一下我们的思路

  reverse_bidirectional_iterator() {}
  explicit reverse_bidirectional_iterator(BidirectionalIterator x)
    : current(x) {}
  BidirectionalIterator base() const { return current; }
  Reference operator*() const {
    BidirectionalIterator tmp = current;
    return *--tmp;
  }
#ifndef __SGI_STL_NO_ARROW_OPERATOR
  pointer operator->() const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_OPERATOR */
  self& operator++() {
    --current;
    return *this;
  }
  self operator++(int) {
    self tmp = *this;
    --current;
    return tmp;
  }
  self& operator--() {
    ++current;
    return *this;
  }
  self operator--(int) {
    self tmp = *this;
    ++current;
    return tmp;
  }
};

我们看库中的*操作符重载,发现它构造了一个临时对象,然后返回的是临时对象减减之后的位置

这到底是为什么呢?

这里有两个问题

1、为什么要返回临时对象

2、为什么要先减减,再返回

这里是有原因的,我们只要想明白一点,这两个问题就都会被解决

以上的两个问题一定跟传入的迭代器有关,因为要使用已经实现的正向迭代器去实现一个反向迭代器。

同时我们要知道,正向迭代器的begin指向第一个有效元素,end指向最后一个元素的下一个位置

我们再看看list中反向迭代器的声明和定义

  iterator begin() { return (link_type)((*node).next); }
  const_iterator begin() const { return (link_type)((*node).next); }
  iterator end() { return node; }
  const_iterator end() const { return node; }
  reverse_iterator rbegin() { return reverse_iterator(end()); }
  const_reverse_iterator rbegin() const { 
    return const_reverse_iterator(end()); 
  }
  reverse_iterator rend() { return reverse_iterator(begin()); }
  const_reverse_iterator rend() const { 
    return const_reverse_iterator(begin());
  } 

我们发现库中的反向迭代器与正向迭代器形成对称,也就是那正向迭代器的begin构造反向迭代器的end,正向迭代器的end构造反向迭代器的begin。

正是这种构造方法所以才会导致反向迭代器的*是这个样子,所以--的原因弄清楚了,接下来是为什么要返回临时对象的原因,这个原因也比较简单,我们平时在使用迭代器的时候,我们都会手动的++或者--迭代器,来完成遍历,如果我们在底层让this自身++或者--,就会导致迭代器指向的位置发生变化,然后我们在外面手动++ --一下,我们就会跳两步,导致有些元素没有被遍历。


反向迭代器也需要考虑const反向迭代器,处理方法与const的正向迭代器的处理方法一样,在模板上传3个参数,根据实例化的不同来选择调用的是普通反向迭代器还是const迭代器

剩下的部分与list实现迭代器的思路大体相同,不过要想清楚++和--以及解引用的实现细节

//reverse_iterator.hpp

#pragma once
#include<iostream>
#include<string>
using namespace std;
namespace ww
{
	template<class Iterator, class Ref, class Ptr>
	struct __reserve_iterator
	{
		typedef __reserve_iterator<Iterator, Ref, Ptr> Riterator;

		__reserve_iterator(Iterator it)
			:_cur(it)
		{}

		Riterator operator++()
		{
			--_cur;
			return *this;
		}

		Riterator operator++(int)
		{
			Iterator tmp(*this);
			--_cur;
			return tmp;
		}

		Ref operator*()
		{
			Iterator tmp = _cur;
			return *--tmp;
		}

		Riterator operator--()
		{
			++_cur;
			return *this;
		}

		Riterator operator--(int)
		{
			Iterator tmp(*this);
			++_cur;
			return tmp;
		}

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

		bool operator!=(const Riterator it)const
		{
			return _cur != it._cur;
		}

		bool operator==(const Riterator it)const
		{
			return _cur == it._cur;
		}


		Iterator _cur;
	};
}


总结


以上就是今天要讲的内容,反向迭代器的模拟实现除了显式的传3个模板参数外,还可以使用迭代器萃取,来解决const迭代器的问题

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值