首页 > 其他分享 > STL之反向迭代器的实现

STL之反向迭代器的实现

时间:2023-06-11 14:31:44浏览次数:48  
标签:const 迭代 iterator STL self 反向 operator reverse

反向迭代器的实现

反向迭代器介绍

反向迭代器和正向迭代器的区别就是

反向迭代器的++/--是倒着走!

那么反向迭代器的本质是什么?——==是一个容器适配器!==

本质就是通过==封装迭代器==,来让其实现我们想要的行为!

也可以通过通过复制一份正向迭代器,然后修改正向迭代器的行为,来实现反向迭代器,但是这样子很麻烦,没有很好的复用代码!

反向迭代器模板的实现

我们可以先看看STL库里面的list中的反向迭代器

image-20230406112718330

==我们可以看到STL库里面的list的反向迭代器本质就是使用正向迭代器封装出来的!==

image-20230406113348988

我们可以发现所谓的反向迭代器就是将在使用++的时候去调用正向的--

使用--去调用正向的++

而且其实所谓的反向迭代器不是一个每一个类都单独设计的!而是用的都是同一份的模板!

==只要任何一个类的迭代器作为模板参数给这个容器适配器!那么就可以转化为那个类的反向迭代器!==——完成了代码的复用!

成员函数和模板参数

namespace MySTL
{
	template<class InputIterator,class Ref,class Ptr>
	class reverse_iterator
	{
	public:
		typedef reverse_iterator<InputIterator,Ref,Ptr> self;
	private:
		InputIterator _it;
	};
}

构造函数

namespace MySTL
{
	template<class InputIterator,class Ref,class Ptr>
	class reverse_iterator
	{
	public:
		typedef reverse_iterator<InputIterator,Ref,Ptr> self;
		reverse_iterator(InputIterator it)
			:_it(it)
		{}//构造函数
	private:
		InputIterator _it;
	};
}

operator*()——解引用重载

namespace MySTL
{
	template<class InputIterator,class Ref,class Ptr>
	class reverse_iterator
	{
	public:
		typedef reverse_iterator<InputIterator,Ref,Ptr> self;
		Ref operator*()const
		{
			InputIterator tmp = _it;
			return *(--tmp);
		}
	private:
		InputIterator _it;
	};
}


为什么要怎么写?==我们发现反向迭代器解引用不是取得现在迭代器的数据,而是取得前面的迭代器的数据!==

image-20230406232610119

==这样我们就很好理解为什么了!要得到的是现在迭代器的前一个迭代器的数据!==

==end(),我们一开始就是指是最后一个元素的下一个!rend也依旧保留了这个概念!,begin()是指第一个元素!那么rbegin也是同理保留了这个概念!==

==因为rend()是begin()封装的,rbegin()是end()封装的! ,只有先去 -- 这样子rend()与rbegin(),才能符合我们一般理解的逻辑!不然rbegin()就是第一个元素的前一个,rend()就是最后一个元素!==

operator-> 重载

namespace MySTL
{
	template<class InputIterator,class Ref,class Ptr>
	class reverse_iterator
	{
	public:
		typedef reverse_iterator<InputIterator,Ref,Ptr> self;
		Ptr operator->()const
		{
			return &(operator*());
		}
		//-> 重载返回的是数据的地址!所以我们可以简单调用一下operator*!
	private:
		InputIterator _it;
	};
}

==->重载返回的是该数据的地址!我们可以直接调用operator*()!因为解引用重载返回的是该数据的引用!然后我们在此基础上取地址!就可以得得到该数据的地址!==

operator++(前置)

namespace MySTL
{
	template<class InputIterator,class Ref,class Ptr>
	class reverse_iterator
	{
	public:
		typedef reverse_iterator<InputIterator,Ref,Ptr> self;
		self& operator++()
		{
			--_it;
			return *this;
		}
	private:
		InputIterator _it;
	};
}

==反向迭代器中的++,就是正向的--

operator--(前置)

namespace MySTL
{
	template<class InputIterator,class Ref,class Ptr>
	class reverse_iterator
	{
	public:
		typedef reverse_iterator<InputIterator,Ref,Ptr> self;
		self& operator--()
		{
			++_it;
			return *this;
		}
	private:
		InputIterator _it;
	};
}


operator++(后置)

namespace MySTL
{
	template<class InputIterator,class Ref,class Ptr>
	class reverse_iterator
	{
	public:
		typedef reverse_iterator<InputIterator,Ref,Ptr> self;
		self operator--(int)
		{
			self temp = _it;
			++_it;
			return temp;
		}

	private:
		InputIterator _it;
	};
}


后置++,是先用后加,是传值返回,返回的是现在这个迭代器的值

operator--(后置)

namespace MySTL
{
	template<class InputIterator,class Ref,class Ptr>
	class reverse_iterator
	{
	public:
		typedef reverse_iterator<InputIterator,Ref,Ptr> self;
		self operator--(int)
		{
			self temp = _it;
			++_it;
			return temp;
		}
	private:
		InputIterator _it;
	};
}

后置--和后置++同理

operator!=

namespace MySTL
{
	template<class InputIterator,class Ref,class Ptr>
	class reverse_iterator
	{
	public:
		typedef reverse_iterator<InputIterator,Ref,Ptr> self;
		bool operator!= (const self& s)const
		{
			return _it != s._it;
		}
	private:
		InputIterator _it;
	};
}

记住一点!==迭代器想不相同看到是内容相不相同!而不是看迭代器本身的地址相不相同!==

全部代码

namespace MySTL
{
	template<class InputIterator,class Ref,class Ptr>
	class reverse_iterator
	{
	public:
		typedef reverse_iterator<InputIterator,Ref,Ptr> self;
		reverse_iterator(InputIterator it)
			:_it(it)
		{}

		Ref operator*()const
		{
			InputIterator tmp = _it;
			return *(--tmp);
		}
		Ptr operator->()const
		{
			return &(operator*());
		}
		//-> 重载返回的是数据的地址!所以我们可以简单调用一下operator*!
		self& operator++()
		{
			--_it;
			return *this;
		}
		self operator++(int)
		{
			self temp = _it;
			--_it;
			return temp;
		}
		self& operator--()
		{
			++_it;
			return *this;
		}
		self operator--(int)
		{
			self temp = _it;
			++_it;
			return temp;
		}

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

list的反向迭代器实现

namespace MySTL
{
    //iterator类的实现,list_node类的实现
	template<class T>
	class list
	{
		typedef list_node<T> node;
	private:
		node* _head;
		size_t _size;
	public:
		typedef __list_iterator<T,T&,T>  iterator;
		typedef __list_iterator<T, const T&,const T*> const_iterator;
		typedef MySTL::reverse_iterator<iterator, T&, T*> reverse_iterator;
		typedef MySTL::reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;
        //这里只列出rbegin与rend的实现
		const_iterator begin()const
		{
			return const_iterator(_head->_next);
		}
		iterator end()
		{
			return iterator(_head);
		}

		const_iterator end()const
		{
			return const_iterator(_head);
		}
        
        //反向迭代器!
		reverse_iterator rend()
		{
			return reverse_iterator(begin());
		}
		reverse_iterator rbegin()
		{
			return reverse_iterator(end());
		}
		const_reverse_iterator rend()const
		{
			return const_reverse_iterator(begin());
		}
		const_reverse_iterator rbegin()const
		{
			return const_reverse_iterator(end());
		}
	};
	void testlist()
	{
		list<int> lt;
		lt.push_back(2);
		lt.push_back(5);
		lt.push_back(7);
		lt.push_back(1);
		list<int>::reverse_iterator rit = lt.rbegin();
		while (rit != lt.rend())
		{
			cout << *rit << " ";
			++rit;
		}
		cout << endl;
		std::vector<int>v = {1, 343, 2, 8, 5, 9};
		const list<int> lt2(v.begin(),v.end());
		list<int>::const_reverse_iterator rit2 = lt2.rbegin();
		while (rit2 != lt2.rend())
		{
			cout << *rit2 << " ";
			++rit2;
		}
	}
};

//test.cpp
#include"mystl_list.h"
int main()
{
	MySTL::testlist();
	return 0;
}

image-20230407143731219

==我们可以直接去使用这个反向迭代器适配器来适配出各种自定义类型的反向迭代器!只要这个自定义类型支持迭代器!==

==无论是vector,deque,list都是通过这种方式来实现反向迭代器的!==

标签:const,迭代,iterator,STL,self,反向,operator,reverse
From: https://blog.51cto.com/u_15835985/6457800

相关文章

  • 第17章 迭代器模式(Iterator Pattern)
    概述在面向对象的软件设计中,我们经常会遇到一类集合对象,这类集合对象的内部结构可能有着各种各样的实现,但是归结起来,无非有两点是需要我们去关心的:一是集合内部的数据存储结构,二是遍历集合内部的数据。面向对象设计原则中有一条是类的单一职责原则,所以我们要尽可能的去分解这些职责......
  • Nginx用作反向代理服务器使用!
        Nginx("enginex")是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP代理服务器。Nginx是由IgorSysoev为俄罗斯访问量第二的Rambler.ru站点开发的,它已经在该站点运行超过三年了。Igor将源代码以类BSD许可证的形式发布。Nginx超越Apache的高性......
  • STL实践指南
    这是一篇指导您如何在Microsoft Visual Studio下学习STL并进行实践的文章。这篇文章从STL的基础知识讲起,循序渐进,逐步深入,涉及到了STL编写代码的方法、STL代码的编译和调试、命名空间(namespace)、STL中的ANSI / ISO字符串、各种不同类型的容器(container)、......
  • BouncyCastle
    目录jar包下载修改配置文件将下载的两个jar包拷贝到%JAVA_HOME%\jre\lib\ext目录下面新建工程demo.javaSM2Util.javaSM3Util.javaSM4Key.javaSM4Util.javaSM4ModeAndPaddingEnum.java运行结果在openEuler(推荐)或Ubuntu或Windows(不推荐)中完成下面任务参考附件内容完成SM2......
  • 迭代器与生成器
    迭代器迭代器可以记住元素的位置只会往前不能往后可以用iter()创建迭代器对象用next()打印出来,可以看到第一个next()的值只会打印第一个可以用for循环遍历出来,for循环是一个特殊的迭代器list1=[1,2,3,4]#创建迭代器对象a=iter(list1)print(next(a))print(ne......
  • BouncyCastle
    任务详情在openEuler(推荐)或Ubuntu或Windows(不推荐)中完成下面任务参考附件内容完成SM2加解密的内容,提交运行结果截图(10‘)完成SM3,SM4算法的调用,提交运行结果截图和代码(15’,选做)BouncyCastle配置1.jar包下载官网:https://www.bouncycastle.org/latest_releases.html......
  • 正向代理和反向代理
    正向代理:它代理了客户端,相当于代理服务器去访问目标网址。服务器不知道真正的用户是谁(解决访问问题)1、隐藏用户真实地址信息。因为代理服务器相当于客户端,所以与目标网站直接交互的是代理服务器而非用户。2、突破ip访问限制。使公司内部搭建的局域网链接互联网。......
  • _STLP_NEW_IO_NAMESPACE
     在vc6环境下,使用stlport时,会出现errorC2653:‘_STLP_NEW_IO_NAMESPACE’:isnotaclassornamespacename 在此种情况下,是因为包含流相关头文件时,使用了这样的格式:#include"iostream.h"或是#include<iostream.h>。而这些文件并不是标准形式,改为#include<iostream>......
  • 下标,指针,迭代器
    1//使用下标遍历数组中的元素2inta[4]={1,2,3,4};3for(size_ti=0;i<4;++i)4{5cout<<a[i]<<endl;6}1//使用下标任意访问数组中某个元素2inta[4]={1,2,3,4};3cout<<a[1]<<endl;1//使用指针访问遍历数组中......
  • R语言无套利区间模型期货期现研究:正向套利和反向套利次数、收益率分析华泰柏瑞300ETF
    全文链接:http://tecdat.cn/?p=31973最近我们被客户要求撰写关于无套利区间模型的研究报告,包括一些图形和统计输出。股指期货的套利交易有助于股指期货实现其价格发现以及风险规避的功能,因此提高套利交易的效率,对于发挥股指期货在经济发展中的作用有着重要的意义本文帮助客户对......