STL-迭代器

1.迭代器

1.1正向迭代器

正向迭代器是用一个类封装的,迭代器类。例如:在vector,string中的迭代器就相当于一个指针,在list类中用一个类来封装一个节点,实质上也还是一个指针,迭代器就相当于指向一个节点的指针。

现在以list为例子,list的迭代器,代码如下:

//迭代器类
// 一个链表指针用迭代器封装,实质上还是一个指针
//迭代器也就相当于指向一个节点的指针
//第一种解决const类型的迭代器
//const迭代器类
template<class T>
struct ListConstIterator
{typedef ListNode<T> Node;typedef ListIterator<T> Self;Node* _node; //一个迭代器节点//迭代器构造ListConstIterator(Node* node) :_node(node){}++it前置++,返回++以后的值Self& operator++(){_node = _node->_next;return *this;}it++后置++Self operator++(int){Self tmp(*this);//浅拷贝,即两个迭代器指针指向同一个空间,直接应用默认拷贝构造_node = _node->_next;return tmp;//拷贝}--itSelf& operator--(){//向前走_node = _node->_prev;return *this;}it--Self operator--(int){Self tmp(*this);_node = _node->_prev;return tmp;}*it解引用,返回的是数据T& operator*(){return _node->data;}==比较两个迭代器相等,即比较迭代器的位置(引用/地址)相同bool operator==(const Self& it){return _node == it._node;}//!=bool operator!=(const Self& it){return _node != it._node;}//->//返回的是数据的地址T* operator->(){return &_node->data;}
};

1.3 正向const迭代器

const迭代器和普通迭代器区别是: const迭代器指向的内容不能被修改!即为const_iterator begin() const,相当于const int *p
而迭代器器本身不能修改是const iterator begin(),也就相当于int * const p
所以普通迭代器和const迭代器的代码差异只在解引用是有差别
第一种解决方法是在普通迭代器的基础上再写一个const迭代器类,代码如下:

普通迭代器:

//const迭代器类
template<class T>
struct ListConstIterator
{typedef ListNode<T> Node;typedef ListIterator<T> Self;Node* _node; //一个迭代器节点//迭代器构造ListConstIterator(Node* node) :_node(node){}++it前置++,返回++以后的值Self& operator++(){_node = _node->_next;return *this;}it++后置++Self operator++(int){Self tmp(*this);//浅拷贝,即两个迭代器指针指向同一个空间,直接应用默认拷贝构造_node = _node->_next;return tmp;//拷贝}--itSelf& operator--(){//向前走_node = _node->_prev;return *this;}it--Self operator--(int){Self tmp(*this);_node = _node->_prev;return tmp;}*it解引用,返回的是数据T& operator*(){return _node->data;}==比较两个迭代器相等,即比较迭代器的位置(引用/地址)相同bool operator==(const Self& it){return _node == it._node;}//!=bool operator!=(const Self& it){return _node != it._node;}//->//返回的是数据的地址T* operator->(){return &_node->data;}
};

const迭代器

//第一种解决const类型的迭代器
//const迭代器类
template<class T>
struct ListConstIterator
{typedef ListNode<T> Node;typedef ListConstIterator<T> Self;Node* _node; //一个迭代器节点//迭代器构造ListConstIterator(Node* node) :_node(node){}++it前置++,返回++以后的值Self& operator++(){_node = _node->_next;return *this;}it++后置++Self operator++(int){Self tmp(*this);//浅拷贝,即两个迭代器指针指向同一个空间,直接应用默认拷贝构造_node = _node->_next;return tmp;//拷贝}--itSelf& operator--(){//向前走_node = _node->_prev;return *this;}it--Self operator--(int){Self tmp(*this);_node = _node->_prev;return tmp;}*it解引用,返回的是数据const T& operator*(){return _node->data;}==比较两个迭代器相等,即比较迭代器的位置(引用/地址)相同bool operator==(const Self& it){return _node == it._node;}//!=bool operator!=(const Self& it){return _node != it._node;}//->//返回的是数据的地址const T* operator->(){return &_node->data;}};

第二种解决方法:由于const迭代器和普通迭代器只有解引用重载的返回值不一样

//普通迭代器
解引用,返回的是数据T& operator*(){return _node->data;}//->//返回的是数据的地址T* operator->(){return &_node->data;}
//const迭代器
解引用,返回的是数据const T& operator*(){return _node->data;}//->//返回的是数据的地址const T* operator->(){return &_node->data;}

由于两个代码差别不大,只是重载的返回值不一样。第一种也会导致代码冗余,所以用模板来解决以下的问题,代码如下:

template<class T,class Ref,class Ptr>
struct ListIterator
{typedef ListNode<T> Node;typedef ListIterator<T,Ref,Ptr> Self;Node* _node; //一个迭代器节点//迭代器构造ListIterator(Node *node):_node(node){}++it前置++,返回++以后的值Self& operator++(){_node = _node->_next;return *this;}it++后置++Self operator++(int){Self tmp(*this);//浅拷贝,即两个迭代器指针指向同一个空间,直接应用默认拷贝构造_node = _node->_next;return tmp;//拷贝}--itSelf& operator--(){//向前走_node = _node->_prev;return *this;}it--Self operator--(int){Self tmp(*this);_node = _node->_prev;return tmp;}*it解引用,返回的是数据//T& operator*()Ref operator*(){return _node->data;}==比较两个迭代器相等,即比较迭代器的位置(引用/地址)相同bool operator==(const Self& it){return _node == it._node;}//!=bool operator!=(const Self& it){return _node != it._node;}//->//返回的是数据的地址//T* operator->()Ptr operator->(){return &_node->data;}
};template<class T>
class list
{
public://重定义节点类名typedef ListNode<T> Node;
private:Node* _head;//哨兵位size_t _size;//链表中节点的个数public:......//第二种方法解决const迭代器类typedef ListIterator<T,T&,T*> iterator;typedef ListIterator<T,const T&,const T*> const_iterator;//迭代器的引用iterator begin(){//iterator it(_head->_next);//有名对象//return it;return iterator(_head->_next);//这是应用的是一个匿名对象}iterator end(){return iterator(_head);}//const迭代器,需要迭代器不能修改,还是迭代器指向的内容?// 迭代器指向的内容不嫩被修改! const iterator不是我们需要的const迭代器//以下是迭代器本身不能修改//const iterator begin()错误const_iterator begin() const{//iterator it(_head->_next);//有名对象//return it;return const_iterator(_head->_next);//这是应用的是一个匿名对象}const_iterator end() const{return const_iterator(_head);}
};

1.3反向迭代器和反向const迭代器

在我们主观意识上,正向迭代器的begin指向的是除去哨兵位的第一个节点,end则是指向最后一个节点下一个节点(即哨兵位头节点)。而我们也会觉得rbegin则是指向最后一个数据,rend指向第一个节点的上一个节点(即哨兵位头节点),如图
反向迭代器

但是,在c++库中我们则见到的是将begin和rend指向的第一个节点,end和rbegin都指向哨兵位头节点,如图
C++库中的反向迭代器
但是库中的解引用时,会是先++,再解引用

//解引用
Ref operator*()
{//return *_it;//解引用的是前一个Iterator tmp = _it;return *(--tmp);
}
#include<iostream>
#include<vector>
#include<string>
using namespace std;//所有容器的反向迭代器
//迭代器适配器//给我vector<T>::iterator,list<int>::iterator//适配出相应的反向迭代器//本来,每个容器都要写一个反向迭代器的类,但是自己写,太费劲了template<class Iterator, class Ref, class Ptr>struct ReverseIterator{typedef ReverseIterator<Iterator, Ref, Ptr> Self;//重命名Iterator _it;//构造//反向迭代器封装一个正向迭代器ReverseIterator(Iterator it) :_it(it){}Ref operator*(){//return *_it;//解引用的是前一个Iterator tmp = _it;return *(--tmp);}Ptr operator->(){//return _it.operator->();return &(operator*());}//++调用迭代器中的--Self& operator++(){--_it;return *this;}Self& operator--(){++_it;return *this;}bool operator!=(const Self& s){return _it != s._it;}};

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

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

相关文章

AUTOSAR的基础软件和功能

AUTOSAR的基础软件和功能 AUTOSAR&#xff08;Automotive Open System Architecture&#xff09;是一个开放且标准化的软件架构&#xff0c;旨在为汽车电子控制单元&#xff08;ECU&#xff09;创建一个可复用和模块化的软件基础。AUTOSAR的基础软件&#xff08;Basic Softwar…

网络构建和设计方法_3. 网络设计

1.层次化网络模型设计 层次化网络设计模型&#xff0c;可帮助设计者按照层次设计网络架构&#xff0c;并对不同层次赋予特定网络功能&#xff0c;选择适合的设备/系统。在典型层次化网络结构中&#xff0c;核心层通常选用具备高可用性和性能优化的高端路由器/交换机&#xff1b…

背靠广汽、小马智行,如祺出行打得过滴滴和百度吗?

©自象限原创 作者丨艾AA 编辑丨薛黎 北京时间6月14日凌晨&#xff0c;在特斯拉股东大会上&#xff0c;马斯克阐述了对Robotaxi&#xff08;自动驾驶出租车&#xff09;商业模式的构想——特斯拉不仅会运营自己的无人驾驶出租车车队&#xff0c;还可以让特斯拉车主们的爱…

微服务开发 —— 项目环境搭建篇

环境搭建 Linux 环境搭建 Linux 环境搭建大家可以使用虚拟机 VMware、VirtualBox 等应用创建虚拟机&#xff0c;使用Vagrant也可以快捷搭建虚拟环境&#xff1b;Windows 中有 WSL2&#xff0c;Windows 中的 Docker 也对 WSL 进行了支持&#xff0c;也是一个不错的选择。或者可…

Windows - 像Linux一样使用alias

前言 阅读本文约2分钟 说明 使用doskey命令 设置别名 查看当前目录 doskey lldir 激活conda的spider环境 doskey spiderconda activate spider 退出conda环境 doskey condaqconda deactivate 查看所有别名 doskey /macros

实现设计开挂|如何设计出坚不可摧的网球拍?

数字揭秘 我们发现自己可能偶尔会以过激的方式表达沮丧或愤怒&#xff0c;哪怕是在公共场合。就算是世界级的网球运动员也无法避免偶尔的情绪爆发&#xff0c;他们有时会砸球拍来释放被压抑的情绪或应对来自竞赛的压力。 网球运动员的情绪爆发已被证明是不可避免的。哪怕是包括…

Linux系统相关函数总结

在应用程序当中&#xff0c;有时往往需要去获取到一些系统相关的信息&#xff0c;譬如时间、日期、以及其它一些系统相关信息&#xff0c;本章将向大家介绍如何通过 Linux 系统调用或 C 库函数获取这些系统信息。除此之外&#xff0c;还会向大家介绍 Linux 系统下的/proc 虚拟文…

浏览器插件利器-allWebPluginV2.0.0.14-beta版发布

allWebPlugin简介 allWebPlugin中间件是一款为用户提供安全、可靠、便捷的浏览器插件服务的中间件产品&#xff0c;致力于将浏览器插件重新应用到所有浏览器。它将现有ActiveX插件直接嵌入浏览器&#xff0c;实现插件加载、界面显示、接口调用、事件回调等。支持谷歌、火狐等浏…

js删除el-table删除新增项,有的已经保存有的未经保存

有时候在弹窗中的弹窗要删除数据,有的是刚新增进来的,没有经过保存就没有id,有的已经保存过就有id 根据情况设定是否为编辑模式,如果为编辑模式就需要进行筛选删除及接口,如果不是编辑模式,只需要进行筛选删除 this.editFlag true; // 为编辑模式// 删除伤亡名单handelDel() …

数据库管理系统(DBMS)

一.数据库管理系统 1.简介 数据库管理系统(Database Management System)是一种操纵和管理数据库的大型软件&#xff0c;用于建立、使用和维护数据库&#xff0c;简称DBMS。它对数据库进行统一的管理和控制&#xff0c;以保证数据库的安全性和完整性。用户通过DBMS访问数据库中…

【PWN · ret2libc | protobuf】[2024CISCN · 华中赛区]protoverflow

套了一层protobuf壳&#xff0c;然后就是简单的ret2libc 参考速递&#xff1a;深入二进制安全&#xff1a;全面解析Protobuf-CSDN博客 前言 第一次遇到protobuf&#xff0c;如果没有了解过&#xff0c;是显然做不出来的。此次复现&#xff0c;也算是点亮了一个技能点 一、什么…

如何用Vue3和Plotly.js实现一个动态3D图的在线展示

本文由ScriptEcho平台提供技术支持 项目地址&#xff1a;传送门 基于 Plotly.js 的交互式图表动画 应用场景 本代码演示了如何使用 Plotly.js 创建交互式图表动画&#xff0c;其中一个区域填充的区域在给定时间间隔内更新其数据。这种动画可用于可视化时间序列数据或展示数…

【监控】1.prometheus的安装

在 macOS 上部署 Grafana 和 Prometheus 来监控 Java 服务是一个非常实用的操作。以下是详细的步骤&#xff0c;包括如何安装和配置 Prometheus、Grafana 以及在 Java 服务中集成 Prometheus 的客户端库来收集指标数据。 1. 安装 Prometheus 1.1 使用 Homebrew 安装 Promethe…

【创建者模式-单例设计模式】

概述 这种模式设计到一个单一的类&#xff0c;该类负责创建自己的对象&#xff0c;同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象方式&#xff0c;可以直接访问&#xff0c;不需要实例化该类的对象。 单例模式的实现 饿汉式&#xff1a;即类的初始化阶段就…

centOS7网络配置_NAT模式设置

第一步&#xff1a;查看电脑网卡 nat模式对应本地网卡的VMnet 8 &#xff0c;查看对应的IP地址。 第二步&#xff1a;虚拟网络编辑器 打开VMWare&#xff0c;编辑--虚拟网络编辑器&#xff0c;整个都默认设置好了&#xff0c;只需要查看对应的DHCP设置中对应的IP的起始&#…

算法金 | 没有思考过 Embedding,不足以谈 AI

大侠幸会&#xff0c;在下全网同名「算法金」 0 基础转 AI 上岸&#xff0c;多个算法赛 Top 「日更万日&#xff0c;让更多人享受智能乐趣」 抱个拳&#xff0c;送个礼 在当今的人工智能&#xff08;AI&#xff09;领域&#xff0c;Embedding 是一个不可或缺的概念。如果你没有…

Python学习笔记24:进阶篇(十三)常见标准库使用之数据压缩功能模块zlib,gzip,bz2,lzma的学习使用

前言 本文是根据python官方教程中标准库模块的介绍&#xff0c;自己查询资料并整理&#xff0c;编写代码示例做出的学习笔记。 根据模块知识&#xff0c;一次讲解单个或者多个模块的内容。 教程链接&#xff1a;https://docs.python.org/zh-cn/3/tutorial/index.html 数据压缩…

2024年度临沂市安全文化书画摄影展开幕

人海信息网山东讯 6月27日&#xff0c;2024年度临沂市安全文化书画摄影作品展&#xff0c;在临沂高新区隆重开幕。本次书画摄影展深入贯彻“以人为本&#xff0c;安全发展”的重要思想&#xff0c;立意高远&#xff0c;内涵丰富&#xff0c;思想深邃&#xff0c;承载着健康、幸…

mysql面试题 Day3

1 什么是最左匹配原则 最左前缀匹配原则是指&#xff1a;msyql会按照联合索引的创建顺序&#xff0c;从左到右开始匹配。 例如创建了一个联合索引(A.B,C)&#xff0c;那么本质上来说&#xff0c;是创建了A,(A,B),(A,B,C)三个索引。 之所以如此&#xff0c;是因为mysql在使用…

List常用操作比for循环更优雅的写法

private String name; //姓名 private Integer age; //年龄 private Integer departId; //所属部门id } List list new ArrayList<>(); 复制代码 简单遍历 使用lamada表达式之前&#xff0c;如果需要遍历list时&#xff0c;一般使用增强for循环&#xff0c;代码如…