【C++】反向迭代器--迭代器适配器

前言

        大家好呀~欢迎进入我的这篇学习笔记~ 我的上一篇C++文章传送点在这里哦:【C++】stack、queue、priority_queue的模拟实现_柒海啦的博客-CSDN博客

        我们知道,在C++的STL容器中,有着一个重要的迭代器,也就是和正向迭代器不一样的反向迭代器。这篇学习笔记,将带大家认清理清楚反向迭代器如何通过正向迭代器进行复用实现,达到一个多种容器都能使用的结果。

        废话不多说,我们直接开始吧:

目录

1.引入

2.代码实现

3.综合代码

4.测试vector和list


1.引入

        在前面,相信大家也见识过了容器适配器。实际上就是在复用STL的其他容器的时候,搞得一个模板参数进行替代,能够做到用不同的容器进行底层实现。只要底层所调用的方法一致就不会出现问题,但是效率问题就要看用户本身是如何去想的了。

        实际上,反向迭代器的实现也就是迭代器适配器的实现。我们只需要控制传入一个正向迭代器,根据此正向迭代器的相同调用完成反向迭代器,已达到不同的容器均可以使用此反向迭代器类模板,只要实现了正向迭代器的类似功能。

         比如我们写一个反向迭代器,让list和vector都能够使用此反向迭代器。(list的正向迭代器封装过,vector的正向迭代器是原生指针)

        要执行反向迭代器,实际上也就是完成和正向迭代器相反的功能(也可以直接写一个反向迭代器,直接使用容器底层的结构,但是这样并没有复用,并且也打不到适配器的效果),正向迭代器++对应反向的--,--对应反向的++,其余类似。

【C++】反向迭代器--迭代器适配器_第1张图片

        如上图所示,每个容器对自己的数据进行一个封装成正向迭代器,使其能像指针那样去访问数据。而反向迭代器无需关系容器内部数据结构,只需要正向迭代器提供相应的功能我来进行封装即可。

2.代码实现

        首先,此反向迭代器自然是模板类,首先是类似于正向迭代器封装实现模板的那一套,T&和T*分开传入。只不过此时数据不再是类型T,而是iterator:

	//         iterator            T&          T*
	template

        定义成struct方便全部设置为public,方便访问,类名和库一致:__reverse_iterator。成员自然就是我们的正向迭代器,把自身调用重命名一下(后面有些接口需要传出自己)

	//         iterator            T&          T*
	template
	struct __reverse_iterator
	{
		Iterator _cur;
		typedef __reverse_iterator reverse_iterator;
    ......
    }

        构造函数需要传入一个正向迭代器,初始化给我们的成员变量:

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

        ++和--分别调用正向迭代器的--和++即可:

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

		reverse_iterator operator++(int)
		{
			reverse_iterator tmp(_cur);
			--_cur;
			return tmp;
		}

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

		reverse_iterator operator--(int)
		{
			reverse_iterator tmp(_cur);
			++_cur;
			return tmp;
		}

        解引用需要注意,因为此时第一个传入的应该是end(rbegin),即反向迭代器是从正向迭代器的end开始遍历,而end是指向数据最后一个的下一个位置,所以我们要在不改变此时所在位置的情况下,访问前一个位置的数据即可:

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

        ->表示指针访问某个成员所用符号,所以我们应该返回指针即地址,所以就复用上面的取值,然后取地址即可:

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

        != 和 == 直接复用正向迭代器的即可:

		bool operator!=(const reverse_iterator& r)
		{
			return _cur != r._cur;
		}

		bool operator==(const reverse_iterator& r)
		{
			return _cur == r._cur;
		}

3.综合代码

#pragma once

// 实现反向迭代器配置  利用原本的迭代器作为容器
namespace YuShen
{
	//         iterator            T&          T*
	template
	struct __reverse_iterator
	{
		Iterator _cur;
		typedef __reverse_iterator reverse_iterator;

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

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

		reverse_iterator operator++(int)
		{
			reverse_iterator tmp(_cur);
			--_cur;
			return tmp;
		}

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

		reverse_iterator operator--(int)
		{
			reverse_iterator tmp(_cur);
			++_cur;
			return tmp;
		}

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

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

		bool operator!=(const reverse_iterator& r)
		{
			return _cur != r._cur;
		}

		bool operator==(const reverse_iterator& r)
		{
			return _cur == r._cur;
		}

	};
}

4.测试vector和list

        分别在list和vector导入后,进行测试:

【C++】反向迭代器--迭代器适配器_第2张图片

 【C++】反向迭代器--迭代器适配器_第3张图片

         vector的具体模拟实现链接在这里哦~:【C++】vector从理解到深入_柒海啦的博客-CSDN博客

        测试代码:

【C++】反向迭代器--迭代器适配器_第4张图片 【C++】反向迭代器--迭代器适配器_第5张图片

 

         可以发现,测试的非常成功。明明两个正向迭代器的底层实现都不相同(一个封装实现,一个原生指针)。其实我们发现反向迭代器的实现利用的都是接口罢了。所以,只要正向迭代器提供相同的接口(++ -- 随机访问等等.....),就能统一的进行实现,此反向迭代器也就有了它作为模板类的意义。

你可能感兴趣的:(C++,c++)