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;非…

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…

计算机网络 第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等新…

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

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

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

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

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…

【MySQL实践】一个隐蔽的问题导致 Field ‘xxx‘ doesn‘t have a default value

文章目录 1.背景2.问题处理3.思考与总结 1.背景 最后在公司的后台系统上遇到了一个线上问题&#xff0c;是在插入某个表数据的时候出现了数据库的插入异常&#xff0c;即&#xff1a;java.sql.SQLException: Field xxx doesnt have a default value&#xff0c;这其实是一个比…

javaweb-js-vue基础知识(持续更新中)

sshu 双向数据绑定 ---------------------------------------------------------- 注意淘宝镜像最新网址发生变化&#xff0c;记得改&#xff0c;不是老师现在用的那个&#xff0c;不然会下载出错&#xff01;&#xff01;&#xff01; 没有的&#xff1a;ctrlshiftp&#xff…

apipost和curl收不到服务器响应的HTTP/1.1 404 Not Found

windows的apipost发送请求后&#xff0c;服务器响应了HTTP/1.1 404 Not Found&#xff0c;但是apipost一直显示发送中。 linux上的curl也一样。 使用wireshark抓包发现收到了响应&#xff0c;但是wireshark识别不了&#xff08;图中是回应404后关闭了连接&#xff09;&#xff…

Chatgpt的崛起之路

Chatgpt的崛起之路 背景与发展历程背景发展历程 技术原理第一阶段&#xff1a;训练监督策略模型第二阶段&#xff1a;训练奖励模型第三阶段&#xff1a;采用强化学习来增强模型的能力。 国内使用情况及应用的领域面临的数据安全挑战与建议ChatGPT获取数据产生的问题数据泄露问题…

接口自动化测试:mock server之Moco工具

什么是mock server mock&#xff1a;英文可以翻译为模仿的&#xff0c;mock server是我们用来解除依赖&#xff08;耦合&#xff09;&#xff0c;假装实现的技术&#xff0c;比如说&#xff0c;前端需要使用某些api进行调试&#xff0c;但是服务端并没有开发完成这些api&#…

测试人年终总结:入行三年,下一步怎么走,思想碰撞

原贴地址&#xff1a;入行三年&#xff0c;下一步怎么走&#xff0c;思想碰撞 TesterHome 熟悉环境&#xff0c;进步缓慢&#xff1b;停止思考&#xff0c;举步不前&#xff08;为什么会有这篇文章why 初心变质&#xff1a;计算机系毕业&#xff0c;毕业时的打算是从测试进&a…