重温设计模式--C++迭代器种类和用法

文章目录

      • 定义
      • 1、 输入迭代器(Input Iterator
      • 2、输出迭代器(Output Iterator)
      • 3、前向迭代器(Forward Iterator)
      • 4、双向迭代器(Bidirectional Iterator)
      • 5、 随机访问迭代器(Random - Access Iterator)

定义

它提供了一种方法来顺序访问一个聚合对象(如数组、列表、树等各种容器类型的数据结构)中的各个元素,而又无需暴露该聚合对象的内部表示

1、 输入迭代器(Input Iterator

  • 定义和特点
    • 输入迭代器是一种只读迭代器,它能够从一个序列中读取元素,并且只能单向向前移动。其主要目的是用于支持对容器元素的顺序读取操作,就像从一个输入流(如std::istream)中读取数据一样。
    • 它支持的操作包括解引用(*操作符)以获取当前元素的值、++操作符来将迭代器移动到下一个元素位置,并且可以通过==!=操作符来比较两个迭代器是否指向相同的位置。但是,一旦迭代器向前移动,就不能再回到之前的位置。
  • 应用场景
    • 适用于单次遍历容器元素的场景,比如在从标准输入读取数据并存入容器后,使用输入迭代器来逐个读取容器中的数据进行处理,且不需要修改数据,也不需要多次遍历。例如,将std::cin读取的整数序列存入std::vector后,使用输入迭代器来计算这些整数的和。
  • 示例代码片段
    • 以下是一个简单的示例,使用std::istream_iterator(这是C++标准库中基于输入迭代器概念实现的迭代器类型)从std::cin读取整数,并存入std::vector,然后再使用输入迭代器遍历vector并输出整数。
    #include <iostream>
    #include <vector>
    #include <iterator>
    int main() {std::vector<int> numbers;std::istream_iterator<int> inputIt(std::cin), endIt;while (inputIt!= endIt) {numbers.push_back(*inputIt);++inputIt;}std::istream_iterator<int> outputIt(numbers.begin());while (outputIt!= numbers.end()) {std::cout << *outputIt << " ";++outputIt;}std::cout << std::endl;return 0;
    }
    

2、输出迭代器(Output Iterator)

  • 定义和特点
    • 输出迭代器主要用于向容器或其他输出目标写入数据,同样是单向的,不过它侧重于数据的输出操作。与输入迭代器类似,它也支持++操作符来移动位置,并且可以通过解引用操作符*来将数据写入到当前位置,但解引用操作主要用于赋值,而不是获取值。
  • 应用场景
    • 常用于将数据写入容器的场景,例如将一个计算结果序列逐个存入容器中。在对容器进行填充新元素的操作,特别是从其他数据源生成数据并填充到容器时,输出迭代器很有用。
  • 示例代码片段
    • 以下示例使用std::ostream_iterator(C++标准库中的输出迭代器类型)将一个整数序列输出到std::cout,它将数据从容器(这里是vector)中逐个取出并输出到控制台。
    #include <iostream>
    #include <vector>
    #include <iterator>
    int main() {std::vector<int> numbers = {1, 2, 3, 4, 5};std::ostream_iterator<int> outputIt(std::cout, " ");for (int num : numbers) {*outputIt = num;++outputIt;}std::cout << std::endl;return 0;
    }
    

3、前向迭代器(Forward Iterator)

  • 定义和特点
    • 前向迭代器在输入迭代器和输出迭代器的基础上提供了更多的功能,它不仅可以单向向前移动,而且可以多次遍历同一个序列。它支持所有输入迭代器和输出迭代器的操作,同时解引用操作更加灵活,既可以读取也可以修改元素的值。
  • 应用场景
    • 在需要对容器元素进行多次读取和修改操作的场景中很有用。例如,在一个算法中,可能需要多次遍历一个容器来更新元素的值,或者在一个容器中查找满足特定条件的元素,然后对这些元素进行修改。
  • 示例代码片段
    • 以下是一个简单的示例,使用自定义的前向迭代器(假设已经有一个自定义的容器类和对应的前向迭代器类实现)来遍历容器并将每个元素的值加倍。
    class MyForwardIterator;
    class MyContainer {
    public:MyForwardIterator begin();MyForwardIterator end();// 其他容器相关的操作
    };
    class MyForwardIterator {
    public:MyForwardIterator& operator++();int& operator*();bool operator==(const MyForwardIterator& other) const;bool operator!=(const MyForwardIterator& other) const;// 其他迭代器相关的操作
    };
    void doubleElements(MyContainer& container) {MyForwardIterator it = container.begin();MyForwardIterator endIt = container.end();while (it!= endIt) {*it *= 2;++it;}
    }
    

4、双向迭代器(Bidirectional Iterator)

  • 定义和特点
    • 双向迭代器在继承前向迭代器功能的基础上,增加了向后移动的能力。它可以通过--操作符将迭代器向反方向移动,从而能够更加灵活地在容器元素之间进行遍历。双向迭代器支持所有前向迭代器的操作,同时还支持反向移动操作。
  • 应用场景
    • 在需要在容器中双向移动的场景中非常有用。例如,在处理双向链表这种数据结构时,或者在一个算法中需要根据某些条件来回遍历容器元素的情况,如在一个排序算法中,可能需要先正向遍历找到一个合适的位置,然后再反向遍历来调整元素的顺序。
  • 示例代码片段
    • std::list为例,std::list的迭代器是双向迭代器。以下代码展示了如何使用双向迭代器在std::list中双向移动并操作元素。
    #include <iostream>
    #include <list>
    int main() {std::list<int> numbers = {1, 2, 3, 4, 5};std::list<int>::iterator it = numbers.begin();// 正向遍历并输出while (it!= numbers.end()) {std::cout << *it << " ";++it;}std::cout << std::endl;it = numbers.end();--it;// 反向遍历并输出while (it!= numbers.begin()) {std::cout << *it << " ";--it;}std::cout << *it << std::endl;return 0;
    }
    

5、 随机访问迭代器(Random - Access Iterator)

  • 定义和特点
    • 随机访问迭代器是功能最强大的一种迭代器类型,它除了支持双向迭代器的所有操作外,还支持通过索引(类似数组下标)的方式直接访问容器中的任意元素。可以使用[]操作符进行随机访问,还可以进行迭代器之间的算术运算,如+-+=-=等操作,来快速地在容器元素之间进行跳转。
  • 应用场景
    • 在需要高效地访问容器中任意位置元素的场景中非常有用。例如,在对数组或者std::vector这种支持随机访问的数据结构进行快速排序、二分查找等算法时,随机访问迭代器能够大大提高算法的效率,因为可以直接定位到需要操作的元素位置,而不需要逐个移动迭代器来访问。
  • 示例代码片段
    • 以下以std::vector为例,展示随机访问迭代器的使用。
    #include <iostream>
    #include <vector>
    int main() {std::vector<int> numbers = {1, 2, 3, 4, 5};std::vector<int>::iterator it = numbers.begin();// 通过随机访问迭代器直接访问第三个元素(索引为2)std::cout << numbers[2] << std::endl;// 使用算术运算移动迭代器it += 3;std::cout << *it << std::endl;return 0;
    }
    
  1. 不是所有的STL迭代器都是随机访问迭代器
    • STL(标准模板库)中有多种容器,每种容器所提供的迭代器类型不同,以适应其内部数据结构的特性和访问需求。
    • 输入迭代器(Input Iterator)和输出迭代器(Output Iterator)相关容器
      • 在一些基于流的操作或者单次单向数据读取/写入场景下会涉及到这两类迭代器相关的概念。例如,istream_iteratorostream_iterator分别是输入迭代器和输出迭代器类型。它们主要用于从输入流(如std::cin)读取数据到容器或者将容器中的数据输出到输出流(如std::cout),这种迭代器不支持随机访问,而是单向的读取或写入操作。
    • 前向迭代器(Forward Iterator)相关容器
      • forward_list(单向链表)是一个典型的提供前向迭代器的容器。前向迭代器可以单向向前移动,并且可以多次遍历序列,但不支持像随机访问迭代器那样通过索引直接访问元素或者进行迭代器的算术运算。例如,对于std::forward_list<int> flist;,其迭代器只能使用++操作符向前移动来遍历链表中的元素。
    • 双向迭代器(Bidirectional Iterator)相关容器
      • list(双向链表)和setmultisetmapmultimap(关联容器)等提供的是双向迭代器。以std::list为例,它的迭代器可以向前和向后移动,通过--操作符实现反向遍历,但是也不支持像随机访问迭代器一样的索引访问方式。例如,对于std::list<int> myList;,可以使用myList.begin()myList.end()获取双向迭代器,然后在列表元素之间双向移动,但不能像在vector中那样使用[]操作符直接访问元素。
  2. 部分STL容器提供随机访问迭代器
    • vectordeque容器
      • vector(动态数组)和deque(双端队列)是STL中提供随机访问迭代器的典型容器。它们内部的数据结构允许通过索引直接访问元素,就像访问数组元素一样。例如,对于std::vector<int> vec;,可以使用vec[3]来直接访问索引为3的元素,也可以通过迭代器进行算术运算,如vec.begin() + 5来获取指向第6个元素(索引为5)的迭代器。这种随机访问的特性使得vectordeque在很多需要高效访问元素的算法中表现出色,比如快速排序、二分查找等算法可以充分利用这种随机访问迭代器的优势来提高效率。
    • array容器
      • array是一个固定大小的数组容器,它也提供随机访问迭代器。由于其大小在编译时就已经确定,和普通数组类似,它支持通过索引直接访问元素,其迭代器也具备随机访问的能力,如std::array<int, 5> arr;,可以使用arr[2]访问元素,也可以利用随机访问迭代器进行其他操作。

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

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

相关文章

SpringbBoot如何实现Tomcat集群的会话管理

在使用 Tomcat 集群时&#xff0c;由于每个 Tomcat 实例的 Session 存储是独立的&#xff0c;导致无法实现 Session 的共享&#xff0c;这可能影响到用户跨节点的访问。为了实现跨 Tomcat 实例共享 Session&#xff0c;可以使用 Spring Session 配合 Redis 进行集中式会话管理。…

机器人C++开源库The Robotics Library (RL)使用手册(三)

进入VS工程,我们先看看这些功能函数及其依赖库的分布关系: rl命名空间下,主要有八大模块。 搞定VS后将逐个拆解。 1、编译运行 根据报错提示,配置相应错误的库(根据每个人安装位置不同而不同,我的路径如下:) 编译所有,Release版本耗时大约10分钟。 以rlPlan运动…

零基础微信小程序开发——页面导航之声明式导航(保姆级教程+超详细)

&#x1f3a5; 作者简介&#xff1a; CSDN\阿里云\腾讯云\华为云开发社区优质创作者&#xff0c;专注分享大数据、Python、数据库、人工智能等领域的优质内容 &#x1f338;个人主页&#xff1a; 长风清留杨的博客 &#x1f343;形式准则&#xff1a; 无论成就大小&#xff0c;…

Linux大数据方向shell

一、概述 shell是一个命令行解释器&#xff0c;它接收应用程序/用户命令&#xff0c;然后调用操作系统内核&#xff0c;还是一个功能相当强大的编程语言&#xff0c;易编写&#xff0c;易调试&#xff0c;灵活性强。 二、shell入门 1.输出hello world touch helloworld.sh&…

Ch9 形态学图像处理

Ch9 形态学图像处理 blog点此处&#xff01;<--------- 四大算子相应性质。 腐蚀、膨胀、开闭之间的含义、关系 文章目录 Ch9 形态学图像处理预备知识(Preliminaries)膨胀和腐蚀(Dilation and Erosion)腐蚀膨胀膨胀与腐蚀的对偶关系 开闭操作(Opening and Closing)开运算闭…

【UE5 C++课程系列笔记】14——GameInstanceSubsystem与动态多播的简单结合使用

效果 通过在关卡蓝图中触发GameInstanceSubsystem包含的委托&#xff0c;来触发所有绑定到这个委托的事件&#xff0c;从而实现跨蓝图通信。 步骤 1. 新建一个C类 这里命名为“SubsystemAndDelegate” 引入GameInstanceSubsystem.h&#xff0c;让“SubsystemAndDelegate”继承…

实战举例——vue.js组件开发

有很多人在问有关Vue的组件开发&#xff0c;虽然之前我的文章里讲过关于前端组件开发的例子&#xff0c;不过作为一个前端技术小白&#xff0c;还是有很多内容需要学习和巩固。我这里用我之前开发过的组件举例&#xff0c;再次为大家简单分享一下基于Vue2和elementUI开发的组件…

devops和ICCID简介

Devops DevOps&#xff08;Development 和 Operations 的组合&#xff09;是一种软件开发和 IT 运维的哲学&#xff0c;旨在促进开发、技术运营和质量保障&#xff08;QA&#xff09;部门之间的沟通、协作与整合。它强调自动化流程&#xff0c;持续集成&#xff08;CI&#xf…

设计宝藏解压密码

设计宝藏官网的解压密码是多少&#xff1f; 设计宝藏解压密码是&#xff1a;memm 设计宝藏一个致力于提供免费资源的宝藏网站。 无论你是Blender、After Effects (AE)、Cinema 4D (C4D)、Premiere Pro (PR)、Photoshop (PS)、Illustrator (AI)的爱好者&#xff0c;还是对CG影…

Android OpenGLES2.0开发(十):FBO离屏渲染

人生是一场单程的旅行&#xff0c;即使有些遗憾我们也没有从头再来的机会&#xff0c;与其纠结无法改变的过去不如微笑着珍惜未来。 Android OpenGLES开发&#xff1a;EGL环境搭建Android OpenGLES2.0开发&#xff08;一&#xff09;&#xff1a;艰难的开始Android OpenGLES2.0…

Magnet: 基于推送的大规模数据处理Shuffle服务

本文翻译自&#xff1a;《Magnet: Push-based Shuffle Service for Large-scale Data Processing》 摘要 在过去的十年中&#xff0c;Apache Spark 已成为大规模数据处理的流行计算引擎。与其他基于 MapReduce 计算范式的计算引擎一样&#xff0c;随机Shuffle操作&#xff08;即…

Pytorch | 利用VA-I-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击

Pytorch | 利用VA-I-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击 CIFAR数据集VA-I-FGSM介绍相关定义算法流程 VAI-FGSM代码实现VAI-FGSM算法实现攻击效果 代码汇总vaifgsm.pytrain.pyadvtest.py 之前已经针对CIFAR10训练了多种分类器&#xff1a; Pytorch | 从零构建AlexNet对…

WebPack3项目升级webpack5的配置调试记录

文章目录 前言一、webpack3环境1.1、知识点记录1.1.1、配置解释1.1.2、webpack与sass版本对应关系1.1.3、CommonJS与ESModule1.1.4、node版本管理nvm1.1.5、sass-loader、sass与node-sass 1.2、其他1.2.1、.d.ts是什么文件1.2.2、react与types/react版本对应关系1.2.3、webpack…

MySQL 数据”丢失”事件之 binlog 解析应用

事件背景 客户反馈在晚间数据跑批后,查询相关表的数据时,发现该表的部分数据在数据库中不存在 从应用跑批的日志来看,跑批未报错,且可查到日志中明确显示当时那批数据已插入到数据库中 需要帮忙分析这批数据丢失的原因。 备注:考虑信息敏感性,以下分析场景测试环境模拟,相关数据…

微信小程序的轮播图学习报告

微信小程序轮播图学习报告 好久都没分享新内容了&#xff0c;实在惭愧惭愧。今天给大家做一个小程序轮播图的学习报告。 先给大家看一下我的项目状态&#xff1a; 很空昂&#xff01;像一个正在修行的老道&#xff0c;空的什么也没有。 但是我写了 4 个 view 容器&#xff0c;…

【RAII | 设计模式】C++智能指针,内存管理与设计模式

前言 nav2系列教材&#xff0c;yolov11部署,系统迁移教程我会放到年后一起更新&#xff0c;最近年末手头事情多&#xff0c;还请大家多多谅解。 上一节我们讲述了C移动语义相关的知识&#xff0c;本期我们来看看C中常用的几种智能指针&#xff0c;并看看他们在设计模式中的运…

微软 CEO 萨提亚・纳德拉:回顾过去十年,展望 AI 时代的战略布局

近日&#xff0c;微软 CEO 萨提亚・纳德拉与著名投资人比尔・格里和布拉德・格斯特纳进行了一场深度对话&#xff0c;回顾了过去十年微软的转型历程&#xff0c;并展望了 AI 时代的战略布局。在这次访谈中&#xff0c;纳德拉分享了他在微软的早期经历&#xff0c;包括他加入微软…

【Java-tesseract】OCR图片文本识别

文章目录 一、需求二、概述三、部署安装四、技术细节五、总结 一、需求 场景需求:是对识别常见的PNG,JPEG,TIFF,GIF图片识别&#xff0c;环境为离线内网。组件要求开源免费&#xff0c;并且可以集成Java生成接口服务。 二、概述 我不做选型对比了,我筛选测试了下Tesseract(v…

iOS开发代码块-OC版

iOS开发代码块-OC版 资源分享资源使用详情Xcode自带代码块自定义代码块 资源分享 自提&#xff1a; 通过网盘分享的文件&#xff1a;CodeSnippets 2.zip 链接: https://pan.baidu.com/s/1Yh8q9PbyeNpuYpasG4IiVg?pwddn1i 提取码: dn1i Xcode中的代码片段默认放在下面的目录中…

如何借助边缘智能网关实现厂区粉尘智能监测告警

在诸如木制品加工、纺织品加工、塑料橡胶制品加工等多种工业生产场景中&#xff0c;粉尘问题的隐患和风险不可小觑。如果缺少对生产环境中粉尘的监测和管理&#xff0c;可能发生易燃易爆、环境污染和工人尘肺等生产事故。 针对工业场景中的粉尘状况监测、管理及预警&#xff0c…