当前位置: 首页 > article >正文

C++:反向迭代器

文章目录

  • 一、什么是反向迭代器?
    • 1.1 反向迭代器与正向迭代器的关系
    • 1.2 反向迭代器实现原理
    • 1.3 反向迭代器代码
  • 二、list中的反向迭代器
    • 2.1 定义
    • 2.2 使用
  • 三、vector中的反向迭代器
    • 3.1 定义
    • 3.2 使用
  • 总结


在这里插入图片描述

一、什么是反向迭代器?

反向迭代器的++就是正向迭代器的–,反向迭代器的–就是正向迭代器的++,因此反向迭代器的实现可以借助正向迭代器,即:反向迭代器内部可以包含一个正向迭代器,对正向迭代器的接口进行包装即可。

1.1 反向迭代器与正向迭代器的关系

反向迭代器其实是由正向迭代器适配出来的,它的++,--与正向迭代器相反,它的rbegin是正向迭代器的end,它的rend是正向迭代器的begin,反向迭代器与正向迭代器是镜面对称的。

反向迭代器也是一个模板,传list的迭代器,就是list的反向迭代器,传vector的迭代器就是vector的反向迭代器。

在这里插入图片描述


1.2 反向迭代器实现原理

反向迭代器的++就是正向迭代器的–,反向迭代器的–就是正向迭代器的++,它的rbegin是正向迭代器的end,它的rend是正向迭代器的begin,因此它的解引用需要返回当前迭代器--的迭代器解引用。

在这里插入图片描述

在这里插入图片描述


1.3 反向迭代器代码

这里为了能有返回值,也要传Ref和Ptr

namespace bit
{
	template<class T, class Ref, class Ptr>
	struct ReverseIterator
	{
		typedef ReverseIterator<T, Ref, Ptr> Self;

		Iterator _it;
		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) const
		{
			return _it != s._it;
		}

	};
}

二、list中的反向迭代器

2.1 定义

首先要typedef出来反向迭代器,像这样:

typedef __list_iterator<T, T&, T*> iterator;
typedef __list_iterator<T, const T&, const T*> const_iterator;

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

接着还要提供对应rbegin与rend的获取:

iterator begin()
{
	//return _head->_next;
	return iterator(_head->_next);
}

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

const_iterator begin() const
{
	//return _head->_next;
	return const_iterator(_head->_next);
}

const_iterator end() const
{
	return _head;
	//return const_iterator(_head);
}

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

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

const_reverse_iterator rbegin() const
{
	return reverse_iterator(end());
}

const_reverse_iterator rend() const
{
	return reverse_iterator(begin());
}

2.2 使用

反向迭代器就像这样使用:

	void test_list()
	{
		list<int> lt;
		lt.push_back(1);
		lt.push_back(2);
		lt.push_back(3);
		lt.push_back(4);

		for (auto e : lt)
		{
			cout << e << " ";
		}
		cout << endl;

		list<int>::reverse_iterator rit = lt.rbegin();
		while (rit != lt.rend())
		{
			cout << *rit << " ";
			++rit;
		}
		cout << endl;
	}
}

三、vector中的反向迭代器

3.1 定义

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;

接着还要提供对应rbegin与rend的获取:

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

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

iterator begin()
{
	return _start;
}

iterator end()
{
	return _finish;
}

const_iterator begin() const
{
	return _start;
}

const_iterator end() const
{
	return _finish;
}

3.2 使用

它的使用从表面上看和list的一模一样

	void test_vector1()
	{
		vector<int> v1;
		v1.push_back(1);
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);
		v1.push_back(5);

		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;

		vector<int>::reverse_iterator rit = v1.rbegin();
		while (rit != v1.rend())
		{
			cout << *rit << " ";
			++rit;
		}
		cout << endl;
	}
}

总结

listvector 的反向迭代器表面上看起来使用相同,但它们背后的实现其实有较大的差异。以下是对 listvector 反向迭代器的区别总结:

  1. 容器结构的不同

    • vectorvector 是连续存储的动态数组,所有元素在内存中是连续排列的,反向迭代器在 vector 中只需调整指针的偏移量。
    • listlist 是一个双向链表,元素分散在不同的内存位置,反向迭代器必须沿着链表的指针进行跳转,而不是简单的指针加减操作。
  2. 访问方式的不同

    • vector 反向迭代器vector 允许随机访问,因此反向迭代器可以通过简单的指针运算快速定位任意元素,比如通过 rit + n 访问偏移 n 的元素。
    • list 反向迭代器list 不支持随机访问,因此不能通过 +- 来偏移反向迭代器,只能通过逐个遍历(++--)来前进或后退。
  3. 底层机制的不同

    • vector 反向迭代器:在 vector 中,反向迭代器其实是基于普通迭代器的简单封装,它只是改变了普通迭代器的前进和后退方向。rbegin() 返回的是指向最后一个元素的迭代器,而 rend() 返回的是第一个元素前面的虚拟位置。
    • list 反向迭代器:在 list 中,反向迭代器是通过链表的前驱指针来完成反向遍历。每次前进时,反向迭代器都会通过前驱指针找到前一个元素的位置,因此遍历时比 vector 复杂得多。

因此,虽然表面上看起来一模一样,实际上编译器替我们完成了复写一遍的行为,这就是模板和适配器造就的迭代器!

谢谢大家!!!🤞🤞🤞💖💖💖☆*: .。. o(≧▽≦)o .。.:*☆

在这里插入图片描述


http://www.kler.cn/news/357560.html

相关文章:

  • STMicroelectronics 意法半导体芯片选型表
  • mongoDB基础知识
  • QT 如何置顶窗口并激活
  • 4G、5G通信中,“网络侧“含义
  • 【Linux】命令行下的增删查改之“查看”
  • 基于SpringBoot的旅游网站的设计与实现
  • Scroll 生态首个 meme 项目 $Baggor,我们可以有哪些期待?
  • 集群与分布式
  • Lua变量
  • 学习eNSP对准备华为认证有哪些帮助?
  • TypeScript中 interface接口 type关键字 enum枚举类型
  • Spring Boot视频网站:安全与可扩展性设计
  • python车牌号OCR识别(centos版)
  • MySQL的安装(windows,Centos,ubuntu)
  • 《深度学习》OpenCV EigenFaces算法 人脸识别
  • 数据抓取时,使用动态IP要注意哪些?
  • 【LeetCode】每日一题 2024_10_20 最小差值 I(模拟/数学/贪心)
  • SQL Server-导入和导出excel数据-注意事项
  • 【数据结构】AVL树(C++实现)
  • OpenCV高级图形用户界面(21)暂停程序执行并等待用户按键输入函数waitKey()的使用