C++初阶-反向迭代器的模拟实现

反向迭代器的模拟实现

  • 一、反向迭代器的定义
  • 二、反向迭代器的功能
    • 2.1 operator++
    • 2.2 operator- -
    • 2.3 operator*
    • 2.4 operator!=
  • 三、list反向迭代器模拟实现完整代码
    • 3.1 list.h
    • 3.2 iterator.h
    • 3.3 test.cpp

一、反向迭代器的定义

  我们反向迭代器的思路是复用正向迭代器的功能,使用一个正向迭代器来创建一个反向迭代器,如果是vector的正向迭代器,创建的就是vector的反向迭代器,如果是list的正向迭代器,创建的就是list的反向迭代器。
  我们之前实现普通迭代器是声明了一个迭代器类。此时,我们也要定义一个反向迭代器类。而这个反向迭代器是由正向迭代器构造而来的。

template<class Iterator,class Ref,class Ptr>
struct ReverseIterator
{typedef ReverseIterator<Iterator,Ref,Ptr> Self;Iterator _cur;ReverseIterator(Iterator it):_cur(it){}
};

  在list类中,我们要重命名一个反向迭代器,并将其调用接口写好。其中关于模板参数的书写,我们要注意一下。
  第一个模板参数是普通迭代器类型。
  第二个是迭代器其指向其数据的数据类型的引用。
  第三个是迭代器其指向其数据的数据类型的指针。
并在此基础上定义好const_iterator

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 <iterator, const T&, const T*> const_reverse_iterator;

  这样的好处是,调用普通的rbegin()则创建普通的反向迭代器,其中operator*的返回值是可修改的。
  而const成员调用的是const类型rbegin(),则创建了const_iterator。
  以下是list中通过普通迭代器构造出反向迭代器的rbegin()、rend()。

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

二、反向迭代器的功能

2.1 operator++

Self& operator++()
{--_cur;return *this;
}Self& operator++(int)
{Self& tmp(_cur);--_cur;return tmp;
}      

2.2 operator- -

Self& operator--()
{++_cur;return *this;
}Self& operator--(int)
{Self& tmp(_cur);++_cur;return tmp;
}

2.3 operator*

  这里先明确一点,在STL中,反向迭代器的rbegin()是由list的end()构造的,也就是_head结点。所以我们在解引用的时候,其实是返回其前一个位置的数据。这样做的好处是为了做到迭代器指向的对称。

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

2.4 operator!=

bool operator!=(const Self& s)
{return _cur != s._cur;
}

三、list反向迭代器模拟实现完整代码

3.1 list.h

#pragma once
#include<assert.h>
#include"Iterator.h"namespace zl
{template<class T>struct list_node{list_node<T>* _next;list_node<T>* _prev;T _data;list_node(const T& x=T()):_next(nullptr),_prev(nullptr),_data(x){}};//1、迭代器要么就是原生指针//2、迭代器要么就是自定义类型对原生指针的封装,模拟指针的行为template<class T,class Ref,class Ptr>struct __list_iterator{typedef list_node<T> node;typedef __list_iterator<T,Ref,Ptr> self;node* _node;__list_iterator(node* n):_node(n){}Ref& operator*(){return _node->_data;}Ptr operator->()    //it->_a1  it->->_a1  本来应该是两个->,但是为了增强可读性,省略了一个->{return &_node->_data;}self& operator++(){_node = _node->_next;return *this;}self operator++(int){self tmp(*this);_node = _node->_next;return tmp;}self& operator--(){_node = _node->_prev;return *this;}self operator--(int){self tmp(*this);_node = _node->_prev;return tmp;}bool operator!=(const self& s){return _node != s._node;}bool operator==(const self& s){return _node == s._node;}};//template<class T, class Ref, class Ptr>//struct __list_reverse_iterator//{//	typedef list_node<T> node;//	typedef __list_reverse_iterator<T, Ref, Ptr> self;//	node* _node;//	__list_reverse_iterator(node* n)//		:_node(n)//	{}//	Ref& operator*()//	{//		return _node->_data;//	}//	Ptr operator->()    //it->_a1  it->->_a1  本来应该是两个->,但是为了增强可读性,省略了一个->//	{//		return &_node->_data;//	}//	self& operator++()//	{//		_node = _node->_prev;//		return *this;//	}//	self operator++(int)//	{//		self tmp(*this);//		_node = _node->_prev;//		return tmp;//	}//	self& operator--()//	{//		_node = _node->_next;//		return *this;//	}//	self operator--(int)//	{//		self tmp(*this);//		_node = _node->_next;//		return tmp;//	}//	bool operator!=(const self& s)//	{//		return _node != s._node;//	}//	bool operator==(const self& s)//	{//		return _node == s._node;//	}//};/*template<class T>struct __list_const_iterator{typedef list_node<T> node;typedef __list_const_iterator<T> self;node* _node;__list_const_iterator(node* n):_node(n){}const T& operator*(){return _node->_data;}self& operator++(){_node = _node->_next;return *this;}self operator++(int){self tmp(*this);_node = _node->_next;return tmp;}self& operator--(){_node = _node->_prev;return *this;}self operator--(int){self tmp(*this);_node = _node->_prev;return tmp;}bool operator!=(const self& s){return _node != s._node;}bool operator==(const self& s){return _node == s._node;}};*/template<class T>class list{typedef list_node<T> node;public:typedef __list_iterator<T,T&,T*> iterator;typedef __list_iterator<T,const T&,const T*> const_iterator;//typedef __list_reverse_iterator<T, T&, T*> reverse_iterator;typedef ReverseIterator <iterator, T&, T*> reverse_iterator;typedef ReverseIterator <iterator, const T&, const T*> const_reverse_iterator;//typedef __list_const_iterator<T> const_iterator;/*reverse_iterator rbegin(){return reverse_iterator(_head->_prev);}reverse_iterator rend(){return reverse_iterator(_head);}*/reverse_iterator rbegin(){return reverse_iterator(end());}reverse_iterator rend(){return reverse_iterator(begin());}iterator begin(){//iterator it(_head->_next);//return it;return iterator(_head->_next);}const_iterator begin() const{//iterator it(_head->_next);//return it;return const_iterator(_head->_next);}iterator end(){//iterator it(_head);//return it;return iterator(_head);}const_iterator end() const{//iterator it(_head);//return it;return const_iterator(_head);}void empty_init(){_head = new node;_head->_next = _head;_head->_prev = _head;}list(){/*_head = new node;_head->_next = _head;_head->_prev = _head;*/empty_init();}template <class Iterator>list(Iterator first, Iterator last){empty_init();while (first != last){push_back(*first);++first;}}//lt2(lt1) 拷贝构造传统写法/*list(const list<T>& lt){empty_init();for (auto e : lt){push_back(e);}}*/void swap(list<T>& tmp){std::swap(_head, tmp._head);}//现代写法list(const list<T>& lt){empty_init();list<T> tmp(lt.begin(), lt.end());swap(tmp);}//lt1=lt3list<T>& operator=(list<T> lt){swap(lt);return *this;}~list(){clear();delete _head;_head = nullptr;}void clear(){iterator it = begin();while (it != end()){//it = erase(it);erase(it++);}}void push_back(const T& x=T()){/*node* tail = _head->_prev;node* new_node = new node(x);tail->_next = new_node;new_node->_prev = tail;new_node->_next = _head;_head->_prev = new_node;*/insert(end(), x);}void push_front(const T& x = T()){insert(begin(), x);}void pop_back(){erase(--end());}void pop_front(){erase(begin());}void insert(iterator pos, const T& x){node* cur = pos._node;node* prev = cur->_prev;node* new_node = new node(x);prev->_next = new_node;new_node->_prev = prev;new_node->_next = cur;cur->_prev = new_node;}iterator erase(iterator pos){assert(pos != end());node* prev = pos._node->_prev;node* next = pos._node->_next;prev->_next = next;next->_prev = prev;delete pos._node;return iterator(next);}private:node* _head;};void print_list(const list<int>& lt){list<int>::const_iterator it = lt.begin();while (it != lt.end()){//(*it) *= 2;cout << *it << " ";++it;}cout << endl;}void test_list1(){list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);list<int>::iterator it = lt.begin();while (it != lt.end()){cout << *it << " ";++it;}cout << endl;for (auto e : lt){cout << e << " ";}cout << endl;print_list(lt);}struct AA{int _a1;int _a2;AA(int a1=0,int a2=0):_a1(a1),_a2(a2){}};void test_list2(){list<AA> lt;lt.push_back(AA(1, 1));lt.push_back(AA(2, 2));lt.push_back(AA(3, 3));//AA* ptrlist<AA>::iterator it = lt.begin();while (it != lt.end()){//cout << (*it)._a1 << (*it)._a2 << endl;cout << it->_a1 << it->_a2 << endl;//cout << it.operator->()->_a1 << ":" << it.operator->()->_a1 << endl;++it;}cout << endl;}void test_list3(){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;auto pos = lt.begin();++pos;lt.insert(pos, 20);for (auto e : lt){cout << e << " ";}cout << endl;lt.push_back(100);lt.push_front(1000);for (auto e : lt){cout << e << " ";}cout << endl;lt.pop_back();lt.pop_front();for (auto e : lt){cout << e << " ";}cout << endl;}void test_list4(){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;lt.clear();for (auto e : lt){cout << e << " ";}cout << endl;lt.push_back(10);lt.push_back(20);lt.push_back(30);lt.push_back(40);for (auto e : lt){cout << e << " ";}cout << endl;}void test_list5(){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> lt2(lt);for (auto e : lt2){cout << e << " ";}cout << endl;list<int> lt3;lt3.push_back(10);lt3.push_back(20);lt3.push_back(30);lt3.push_back(40);lt3.push_back(50);for (auto e : lt3){cout << e << " ";}cout << endl;lt = lt3;for (auto e : lt){cout << e << " ";}cout << endl;}void test_list6(){list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);list<int>::iterator it = lt.begin();while (it != lt.end()){cout << *it << " ";++it;}cout << endl;list<int>::reverse_iterator rit = lt.rbegin();while (rit != lt.rend()){cout << *rit << " ";++rit;}cout << endl;}}

3.2 iterator.h

#pragma oncenamespace zl
{//vector::iterator//list::iterator//deque::iteratortemplate<class Iterator,class Ref,class Ptr>struct ReverseIterator{typedef ReverseIterator<Iterator,Ref,Ptr> Self;Iterator _cur;ReverseIterator(Iterator it):_cur(it){}Ref operator*(){Iterator tmp = _cur;--tmp;return *tmp;}Self& operator++(){--_cur;return *this;}Self& operator--(){++_cur;return *this;}bool operator!=(const Self& s){return _cur != s._cur;}};
}

3.3 test.cpp

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<vector>
#include<list>
#include <functional>
#include<algorithm>
#include<string>
using namespace std;
#include "list.h"
#include"Iterator.h"
#include"vector.h"int main()
{//zl::test_list1();//zl::test_list2();//zl::test_list3();//zl::test_list4();//zl::test_list5();zl::test_list6();//zl::test_vector8();//std::vector<int>::iterator it;//cout << typeid(it).name() << endl;return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/232824.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STM32F407-14.3.12-01使用断路功能

使用断路功能 使用断路功能时&#xff0c;根据其它控制位&#xff08;TIMx_BDTR 寄存器中的 MOE⑨、OSSI⑪ 和 OSSR⑩ 位以及 TIMx_CR2 寄存器中的 OISx⑰ 和 OISxN⑱ 位&#xff09;修改输出使能信号和无效电平。任何情况下&#xff0c;OCx③ 和 OCxN④ 输出都不能同时置为有效…

LD2450-24G人体移动跟踪轨迹雷达模块

文章目录 前言一、LD2450简介特点引脚定义 二、使用步骤上位机使用方法通信协议协议格式数据输出协议 雷达命令配置方式串口解析示例 前言 运动目标跟踪是指在区域内实时跟踪运动目标所在的位置&#xff0c;实现对区域内运动目标测距、测角和测速。LD2450是海凌科24G毫米波雷达…

WFrest 库:快速、高效的基于workflow的C++异步 Web 框架

在这篇博客中&#xff0c;我将介绍 WFrest 库&#xff0c;一个基于 C Workflow 企业级程序引擎的异步 Web 框架。WFrest 库能够帮助开发者快速搭建 HTTP 服务器&#xff0c;实现高效的 Web 应用开发。 一、WFrest 库的背景 WFrest 库是一个由[作者/团队]开发的开源项目&#…

基于paddlepaddle的FPS最远点采样

什么是FPS最远点采样&#xff1f; 最远点采样&#xff08;Farthest Point Sampling&#xff0c;FPS&#xff09;是一种常用的采样算法&#xff0c;主要用于点云数据&#xff08;如激光雷达点云数据、分子坐标等&#xff09;的采样。 为了方便解释&#xff0c;定义一下待采样点…

深入解析线程安全的Hashtable实现

目录 引言 1. Hashtable简介 2. Hashtable线程安全实现原理 2.1. 锁机制 2.2. 分段锁 2.3. CAS操作 3. 线程安全策略 3.1. 同步方法 3.2. 分段锁优化 3.3. 乐观锁和CAS 4. 性能优化 4.1. 负载均衡 4.2. 惰性加载 5. 注意事项 5.1. 死锁和性能问题 5.2. 内存开销…

嵌入式软件测试(黑盒测试)---三年嵌入式软件测试的理解

文章内容为本人这三年来在嵌入式软件测试&#xff08;黑盒&#xff09;上的一些积累吧&#xff0c;说起来也挺快的&#xff0c;毕业三年的时间就这样过去了&#xff0c;在两家公司工作过&#xff08;现在这家是第二家&#xff09;&#xff0c;这几年的测试项目基本都是围绕着嵌…

深入探索Zookeeper的ZAB协议:分布式系统的核心解析

引言 自我进入软件开发领域以来&#xff0c;我一直对分布式系统充满着浓厚的兴趣。在这个领域中&#xff0c;Zookeeper无疑是一个备受关注的重要组件。作为一名资深的Java工程师&#xff0c;我有幸深入探索过Zookeeper的许多方面&#xff0c;其中最让我着迷的部分莫过于其核心机…

第十三章 枚举类型和泛型

枚举类型可以取代以往的常用的定义方式&#xff0c;即将常量封装在类或者接口中&#xff0c;此外它还提供了安全检查功能。枚举类型本质上还剋以类的形式存在。泛型的出现不仅可以让程序员少写一些代码&#xff0c;更重要的是它可以解决类型安全问题。泛型提供了编译时的安全检…

redolog有什么用,是怎么工作的

redolog其实就是想干一件事&#xff1a;当一个事务commit了&#xff0c;那肯定是在内存中改了&#xff0c;但是在磁盘里未必。可能刚提交事务就宕机了&#xff0c;还没来得及写磁盘&#xff08;并且也不会立刻写的&#xff0c;会隔一段时间才刷&#xff09;。redolog就是要保证…

关于设计师的自我评价(合集)

设计师的自我评价篇一 本人接受过正规的美术教育&#xff0c;具有较好的美术功底及艺术素养&#xff0c;能够根据公司的需要进行设计制作&#xff0c;熟练掌握多种电脑制作软件&#xff0c;能够高效率地完成工作。本人性格开朗、思维活跃、极富创造力&#xff0c;易于沟通&…

软件测试必会:cookie、session和token的区别

今天就来说说session、cookie、token这三者之间的关系&#xff01;最近这仨玩意搞得头有点大&#x1f923; 01 为什么会有它们三个 我们都知道 HTTP 协议是无状态的&#xff0c;所谓的无状态就是客户端每次想要与服务端通信&#xff0c;都必须重新与服务端链接&#xff0c;意…

奇怪的资源分享

说明一下 最近找了宝宝巴士的资源&#xff0c;下了半天结果发现要解压密码&#xff0c;还甩出付费二维码&#xff0c;气坏我了。要我付钱怎么可能&#xff0c;打死我都不会付钱的。于是我找了另外的资源。这里分享一下这个资源。 宝宝巴士视频版 链接 宝宝巴士压缩版 链接 …

Selenium Wire - 扩展 Selenium 能够检查浏览器发出的请求和响应

使用 Selenium 进行自动化操作时&#xff0c;会存在很多的特殊场景&#xff0c;比如会修改请求参数、响应参数等。 本篇将介绍一款 Selenium 的扩展&#xff0c;即能够检查浏览器发出的请求和响应 - Selenium Wire。 简介 Selenium Wire 扩展了 Selenium 的 Python 绑定&…

24--泛型与Collections工具类

1、泛型 1.1 泛型概述 在前面学习集合时&#xff0c;我们都知道集合中是可以存放任意对象的&#xff0c;只要把对象存储集合后&#xff0c;那么这时他们都会被提升成Object类型。当我们在取出每一个对象&#xff0c;并且进行相应的操作&#xff0c;这时必须采用类型转换。 p…

聊聊15年进入中专计算机的道路

仍记得笔者是参加2015年杭州市中考&#xff0c;优质高中的录取分数线是454分&#xff0c;而我439分&#xff0c;父亲想让我读个民办普通高中。而我将这个志愿排在了计算机专业之后。我成功进入了一所计算机中专。命运之轮就这样悄悄转动。 1、为什么当初选择计算机行业 中考没…

Halcon深度学习相关术语介绍

1、深度学习术语表一 序号 术语 解释 1 Adam Adam (adaptive moment estimation)是一种基于一阶梯度的随机目标函数优化算法&#xff0c;用于计算单独的自适应学习率。在深度学习方法中&#xff0c;该算法可用于最小化损失函数。 2 anchor 它们作为固定的参考边界框&am…

C语言第五十四弹---模拟使用strstr函数

使用C语言模拟使用strstr函数 定义&#xff1a;strstr 是一个 C 标准库函数&#xff0c;用于在一个字符串中查找另一个字符串的第一次出现位置。strstr 函数的声明如下&#xff1a; char* strstr(const char* haystack, const char* needle);它接受两个参数&#xff1a;haysta…

Sectigo DV多域名证书能保护几个域名

多域名SSL证书不限制受保护的域名的类型&#xff0c;可以时多个主域名或者子域名&#xff0c;多域名SSL证书都可以同时保护&#xff0c;比较灵活。但是&#xff0c;多域名https证书并不是免费无限制保护域名数量&#xff0c;一把的多域名SSL证书默认保护3-5个域名记录&#xff…

云原生之深入解析强大的镜像构建工具Earthly

一、Earthly 简介 Earthly 是一个更加高级的 Docker 镜像构建工具&#xff0c;Earthly 通过自己定义的 Earthfile 来代替传统的 Dockerfile 完成镜像构建&#xff1b;Earthfile 就如同 Earthly 官方所描述: Makefile Dockerfile Earthfile在使用 Earthly 进行构建镜像时目前…

定义和使用类的许多重要方面的总结

11.7 总结 本章介绍了定义和使用类的许多重要方面,其中的一些内容可能较难理解,但随着实践经验的不断增 加,读者将逐渐掌握它们。 般来说,访问私有类成员的惟一方法是使用类方法。C使用友元函数来避开这种限制。要让函数 成为友元,需要在类声明中声明该函数,并在声明前加上关…