C++:反向迭代器-reverse_iterator

目录

1.关于反向迭代器

2.反向迭代器的成员函数

1.构造

2.base

3.operator*

4.operator++

5.operator--

6.operator->

7.operator[]

3.反向迭代器的模拟实现

小结


1.关于反向迭代器

在C++中,可以使用反向迭代器来逆序遍历容器中的元素。反向迭代器是通过rbegin()和rend()方法来获取的,它们分别指向容器的最后一个元素和第一个元素的前一个位置。

此类反转双向或随机访问迭代器循环访问范围的方向。

原始迭代器(基础迭代器)的副本保留在内部,用于反映在reverse_iterator上执行的操作:每当reverse_iterator递增时,其基本迭代器就会减少,反之亦然。可以随时通过调用成员 base 获取具有当前状态的基迭代器的副本。

但请注意,当迭代器被反转时,反转的版本不会指向范围内的同一元素,而是指向它前面的元素。

反向迭代器的操作和正向迭代器大致相同,但是要特别注意++操作符,它会使反向迭代器指向前一个元素。

2.反向迭代器的成员函数

reverse_iterator的成员函数实现了反向迭代器的基本功能

下面介绍一些常用的功能:

1.构造

(1) 默认构造函数
构造一个不指向任何对象的反向迭代器。内部基迭代器是值初始化的。
(2) 初始化构造函数
从某个原始迭代器构造一个反向迭代器。构造对象的行为复制了原始对象,只是它以相反的顺序迭代其尖元素。
(3) 复制/类型转换构造函数
从其他反向迭代器构造反向迭代器。构造的对象保持与rev_it相同的迭代感。 

2.base

返回基迭代器的拷贝。

基迭代器是与用于构造reverse_iterator的迭代器类型相同的迭代器,但指向reverse_iterator当前指向的元素旁边的元素(reverse_iterator相对于其基迭代器的偏移量始终为 -1)。

// reverse_iterator::base example
#include <iostream>     // std::cout
#include <iterator>     // std::reverse_iterator
#include <vector>       // std::vectorint main () {std::vector<int> myvector;for (int i=0; i<10; i++) myvector.push_back(i);typedef std::vector<int>::iterator iter_type;std::reverse_iterator<iter_type> rev_end (myvector.begin());std::reverse_iterator<iter_type> rev_begin (myvector.end());std::cout << "myvector:";for (iter_type it = rev_end.base(); it != rev_begin.base(); ++it)std::cout << ' ' << *it;std::cout << '\n';return 0;
}

3.operator*

返回对迭代器指向的元素的引用。

在内部,该函数减少其基本迭代器的副本,并返回取消引用它的结果。

迭代器应指向某个对象,以便可取消引用。

4.operator++

将reverse_iterator提升一个位置。

在内部,预增量版本 (1) 递减对象保留的基本迭代器(就像对它应用运算符一样)。

递增版本 (2) 的实现行为等效于:

reverse_iterator operator++(int) {reverse_iterator temp = *this;++(*this);return temp;
}

5.operator--

将reverse_iterator减少一个位置。

在内部,预递减版本 (1) 递增对象保留的基本迭代器(就像对其应用运算符 ++ 一样)。

递减后版本 (2) 的实现行为等效于:

reverse_iterator operator--(int) {reverse_iterator temp = *this;--(*this);return temp;
}

6.operator->

 返回指向迭代器指向的元素的指针(以便访问其成员之一)。

pointer operator->() const {return &(operator*());
}

7.operator[]

访问距离迭代器当前指向的元素 n 个位置的元素。

如果此类元素不存在,则会导致未定义的行为。

在内部,该函数访问其基本迭代器的适当元素,返回与:base()[-n-1] 相同的元素。

// reverse_iterator::operator[] example
#include <iostream>     // std::cout
#include <iterator>     // std::reverse_iterator
#include <vector>       // std::vectorint main () {std::vector<int> myvector;for (int i=0; i<10; i++) myvector.push_back(i);  // myvector: 0 1 2 3 4 5 6 7 8 9typedef std::vector<int>::iterator iter_type;std::reverse_iterator<iter_type> rev_iterator = myvector.rbegin();std::cout << "The fourth element from the end is: " << rev_iterator[3] << '\n';return 0;
}

3.反向迭代器的模拟实现

这里的反向迭代器与自定义的vector适配,定义了基本功能。

#pragma once
namespace wjc
{template<class Iterator,class Ref,class Ptr>struct Reverse_iterator{Iterator _it;typedef Reverse_iterator<Iterator, Ref, Ptr> self;Reverse_iterator(Iterator it):_it(it){}Ref operator*(){Iterator tmp = _it;return *(--tmp);}Ptr operator->(){return &(operator*());}self& operator++()//前置++{--_it;return *this;}self& operator++(int)//后置++{--_it;return *this;}self& operator--()//前置--{++_it;return *this;}self& operator--(int)//后置--{++_it;return *this;}bool operator!=(const self&s){return _it != s._it;}};template <class T>class vector{public:typedef T* iterator;typedef const T* const_iterator;typedef Reverse_iterator<iterator, T&, T*> reverse_iterator;typedef Reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;const_reverse_iterator rebegin() const{return const_reverse_iterator(end());}const_reverse_iterator reend() const{return const_reverse_iterator(begin());}reverse_iterator rebegin() {return reverse_iterator(end());}reverse_iterator reend() {return reverse_iterator(begin());}vector(): _start(nullptr), _finish(nullptr), _endofstorage(nullptr){}vector(const vector<T>& v){reserve(v.capacity());for (const auto& e : v){push_back(e);}}iterator begin(){return _start;}iterator end(){return _finish;}const_iterator begin() const{return _start;}const_iterator end() const{return _finish;}size_t capacity()const{return _endofstorage - _start;}size_t size()const{return  _finish - _start;}void push_back(const T& a){if (_finish == _endofstorage){size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;reserve(newcapacity);}*_finish = a;_finish++;}void swap(vector<T>& v){std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_endofstorage, v._endofstorage);}vector<T>& operator=(vector<T> v){swap(v);return *this;}~vector(){if (_start){delete[] _start;_start = _finish = _endofstorage = nullptr;}}void reserve(size_t n){if (n > capacity()){size_t oldsize = size();T* tmp = new T[n];if (_start){/*memcpy(tmp, _start, sizeof(T) * oldsize);*/for (size_t i = 0; i < oldsize; i++){tmp[i] = _start[i];}delete[] _start;}_start = tmp;_finish = _start + oldsize;_endofstorage = _start + n;}}void resize(size_t n, T val = T()){if (n > size()){reserve(n);while (_finish < _start + n){*_finish = val;++_finish;}}else{_finish = _start + n;}}void pop_back(){assert(size() > 0);--_finish;}void insert(iterator pos, T x){assert(pos <= _finish);assert(pos >= _start);size_t len = pos - _start;if (_finish == _endofstorage){reserve(capacity() == 0 ? 4 : capacity() * 2);//pos 扩容失效//更新pos位置pos = _start + len;}memmove(pos + 1, pos, (_finish - pos) * sizeof(T));*pos = x;++_finish;}void erase(iterator pos){assert(pos < _finish);assert(pos >= _start);iterator it = pos + 1;while (it < _finish){*(it - 1) = *it;++it;}_finish--;}T& operator[](size_t pos){assert(pos, size());return _start[pos];}const T& operator[](size_t pos)const{assert(pos, size());return _start[pos];}template<class InputIterator>vector(InputIterator first, InputIterator last){while (first != last){push_back(*first);++first;}}private:iterator _start;iterator _finish;iterator _endofstorage;};}

测试

#define  _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include"iterator.h"int main()
{wjc::vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);v.push_back(6);wjc::vector<int>::reverse_iterator it = v.rebegin();while (it != v.reend()){cout << *it << " ";it++;}return 0;
}

 

小结

        在使用反向迭代器时要注意迭代器的失效问题,特别是在进行插入和删除操作时,要小心迭代器的有效性。

        总之,反向迭代器是一个非常有用的工具,可以方便地逆序遍历容器中的元素,提供了在处理逆序数据时的便利。

 

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

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

相关文章

链表的中间结点,简单的快慢指针问题

总结 struct ListNode* middleNode(struct ListNode* head) {struct ListNode*fasthead;struct ListNode*slowhead;while( fast && fast->next)//结束条件{slowslow->next;fastfast->next->next;}return slow; }

组件冲突、data函数、组件通信

文章目录 1.组件的三大组成部分 - 注意点说明2.组件的样式冲突&#xff08;用 scoped 解决&#xff09;3.data是一个函数4.组件通信1.什么是组件通信&#xff1f;2.不同的组件关系 和 组件通信方案分类 5.prop详解prop 校验①类型校验②完整写法&#xff08;类型&#xff0c;非…

面试项目问题

1. 你们这个项目多少人在做?人员分布是怎样的?做了多长时间? 我们项目组一共十个人&#xff0c;包括四个后端开发人员、两个前端开发人员、两个测试人员和两个产品经理。 从需求分析、设计、开发到测试上线到最后的维护阶段&#xff0c;整个项目的周期大概是六个月左右。 …

REVIT二次开发设置门垛高度

步骤1 步骤2 步骤3 using System; using System.Collections.Generic; using System.Linq; using System

Redis 持久化详解:RDB 与 AOF 的配置、触发机制和实际测试

什么是持久化&#xff1f; 就是 Redis 将内存数据持久化到硬盘&#xff0c;避免从数据库恢复数据。之所以避免从数据库恢复数据是因为后端数据通常有性能瓶颈&#xff0c;大量数据从数据库恢复可能会给数据库造成巨大压力。 Redis 持久化通常有 RDB 和 AOF 两种方式&#xff…

《开始使用PyQT》 第01章 PyQT入门 02 安装Python3和PyQT6

02 安装Python3和PyQT6 《开始使用PyQT》 第01章 PyQT入门 02 安装Python3和PyQT6 So that all readers are on the same page, let’s begin by installing or updating your version of Python. 为了让所有读者都能理解&#xff0c;让我们从安装或更新 Python 版本开始。 …

计算机网络 第5章(运输层)

系列文章目录 计算机网络 第1章&#xff08;概述&#xff09; 计算机网络 第2章&#xff08;物理层&#xff09; 计算机网络 第3章&#xff08;数据链路层&#xff09; 计算机网络 第4章&#xff08;网络层&#xff09; 计算机网络 第5章&#xff08;运输层&#xff09; 计算机…

vue3之 websoket发送消息

1.封装websoket var ws null; //建立的连接 var lockReconnect false;//是否真正建立连接 var timeout 6 * 1000 * 5;//30秒一次心跳 var timeoutObj null;//心跳心跳倒计时 var serverTimeoutObj null;//心跳倒计时 var timeoutnum null;//断开 重连倒计时 var global_…

DA14531平台secondary_bootloade工程修改笔记

DA14531平台secondary_bootloade工程修改笔记 1.支持在线仿真 初始时加入syscntl_load_debugger_cfg(); 表示可以重复Jlink连接调试仿真 2.支持串口烧录&#xff0c;和支持单线线写 utilities\secondary_bootloader\includes\bootloader.h /************** 2-wire UART supp…

Siamese network 孪生神经网络--一个简单神奇的结构

1.名字的由来 Siamese和Chinese有点像。Siam是古时候泰国的称呼&#xff0c;中文译作暹罗。Siamese也就是“暹罗”人或“泰国”人。Siamese在英语中是“孪生”、“连体”的意思&#xff0c;这是为什么呢&#xff1f; 十九世纪泰国出生了一对连体婴儿&#xff0c;当时的医学技术…

点赞!HashData连续三年获评数据猿“最具投资价值企业奖”

近日&#xff0c;由上海市经济和信息化委员会、上海市科学技术委员会指导&#xff0c;数据猿和上海大数据联盟共同主办的“第六届金猿季&魔方论坛——大数据产业发展论坛”在上海举行。本次活动以“小趋势大未来”为主题&#xff0c;展示了大数据与人工智能、云计算、5G等新…

【jetson笔记】ubuntu设置代理解决访问github问题

目录 手机开启热点jetson设置代理查询手机ip地址设置反向代理设置全局代理仅设置github全局代理 手机开启热点 手机开启热点并打开clashclash中设置-覆写-启用允许来自互联网的连接确保手机可以访问githubjetson设备连接手机热点 jetson设置代理 查询手机ip地址 设置-我的设…

python csv柱状图统计

import os import pandas as pd import numpy as np import matplotlib.pyplot as plt# 获取当前工作目录 current_directory os.getcwd()# 构建文件路径 file_name cliff.csv file_path os.path.join(current_directory, file_name)# 从CSV文件中读取数据 df pd.read_csv(…

仰暮计划|“她已跨过了八旬的门槛,一个人见证了时光洪流的智慧年代”

倾听与关爱 2023年7月4日中午&#xff0c;我跟随“羽翼”社会实践服务队、党员服务小组一起到柏桥村完成我们本次三下乡的调研任务&#xff0c;通过走访当地居民并与当地党群服务中心干部进行交谈了解当地乡村振兴落实情况。 在走往柏桥村的路上&#xff0c;我有幸遇到了教师…

【操作系统】实验六 分析源代码

&#x1f57a;作者&#xff1a; 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤️关注对我真的很重要&…

在React中使用React.createRef:更优雅的DOM引用方式

在React中使用React.createRef&#xff1a;更优雅的DOM引用方式 React提供了多种方式来引用DOM元素&#xff0c;其中React.createRef()是一种更为现代、更优雅的方式。在这篇博客中&#xff0c;我们将深入了解React.createRef()的应用&#xff0c;以及它为开发者带来的便利。 …

Vulnhub-FUNBOX: GAOKAO渗透

文章目录 前言1、靶机ip配置2、渗透目标3、渗透概括 开始实战一、信息获取二、爆破FTP服务三、GetShell四、提权 前言 由于在做靶机的时候&#xff0c;涉及到的渗透思路是非常的广泛&#xff0c;所以在写文章的时候都是挑重点来写&#xff0c;尽量的不饶弯路。具体有不不懂都的…

仰暮计划|“他说,他是出生于两个时代的人”

凌保庆老爷爷&#xff0c;1942年10月4日出生&#xff0c;今年82岁&#xff0c;家住在河南省登封市唐庄乡磨沟村。7月28日&#xff0c;我作为仰暮计划小队的一员去拜访了这位老人&#xff0c;听凌爷爷讲述了他的故事。 走进这户人家的时候&#xff0c;凌爷爷正在书房里。虽然家…

Spring第三天

今日目标 能够理解AOP的作用 能够完成AOP的入门案例 能够理解AOP的工作流程 能够说出AOP的五种通知类型 能够完成"测量业务层接口万次执行效率"案例 能够掌握Spring事务配置 一、AOP 1 AOP简介 问题导入 问题1&#xff1a;AOP的作用是什么&#xff1f; 问题2&am…

✨JavaScript 第十一章(深入理解null与undefined)

在JavaScript的世界里&#xff0c;null和undefined是两个表示“没有值”的概念&#xff0c;但它们之间有着微妙的差别。undefined是当一个变量被声明了&#xff0c;但没有被赋值时&#xff0c;它的默认值。这是JavaScript引擎的工作&#xff0c;我们通常不会手动设置一个变量为…