c++之迭代器

 

目录

 一、迭代器

二、几种常见的迭代器类型

三、使用迭代器时注意事项


 一、迭代器

在C++中,迭代器是一种用于遍历容器元素的对象。迭代器提供了一种通用的方式来访问各种不同类型的容器,如数组、向量、列表、集合和映射等。

使用迭代器可以避免直接操作容器内部的数据结构,从而提高代码的可读性和可维护性。通过迭代器,可以以一种统一的方式来遍历容器,并且可以在遍历过程中对容器进行各种操作,如查找、插入、删除和排序等。

迭代器的基本操作包括解引用、递增和递减。解引用操作用于访问当前迭代器指向的元素,递增和递减操作用于将迭代器移动到容器中的下一个或上一个元素。

#include <iostream>
#include <vector>using namespace std;int main() {vector<int> vec = {1, 2, 3, 4, 5};// 遍历vector并输出每个元素的值for (auto it = vec.begin(); it != vec.end(); ++it) {cout << *it << " ";}cout << endl;// 在vector的末尾插入一个元素vec.insert(vec.end(), 6);// 遍历vector并输出每个元素的值for (auto it = vec.begin(); it != vec.end(); ++it) {cout << *it << " ";}cout << endl;// 查找vector中是否存在元素4auto it = find(vec.begin(), vec.end(), 4);if (it != vec.end()) {cout << "Found element 4 at position " << distance(vec.begin(), it) << endl;} else {cout << "Element 4 not found" << endl;}return 0;
}

在上面的代码中,我们使用迭代器遍历了一个vector容器,并且输出了每个元素的值。然后,我们在vector的末尾插入了一个新元素,并且再次遍历了vector。

接下来,我们使用STL库中的find函数查找vector中是否存在元素4。如果找到了该元素,则输出它所在的位置;否则输出未找到该元素的信息。

需要注意的是,迭代器不仅可以用于遍历容器元素,还可以用于对容器进行各种操作,如插入、删除和排序等。例如,在vector容器中,我们可以使用insert函数在任意位置插入新元素,使用erase函数删除指定位置的元素,使用sort函数对元素进行排序等。这些操作都可以通过迭代器来实现。

二、几种常见的迭代器类型

在C++中,每种容器都有自己特定的迭代器类型。以下是几种常见的迭代器类型:

  1. begin()end():这是最基本的迭代器类型,用于指向容器中的第一个元素和最后一个元素之后的位置。例如,在vector中,begin() 返回指向第一个元素的迭代器,而 end() 返回指向最后一个元素之后位置的迭代器。

  2. rbegin()rend():这些是反向迭代器类型,用于从容器的末尾向前遍历元素。例如,在vector中,rbegin() 返回指向最后一个元素的迭代器,而 rend() 返回指向第一个元素之前位置的迭代器。

  3. cbegin()cend()crbegin()crend():这些是常量迭代器类型,用于指向容器中的元素,但不允许修改它们的值。这些迭代器可以用于遍历和访问容器中的元素,但不能用于修改它们。

迭代器的常见操作包括:

  1. 解引用:使用*操作符可以访问当前迭代器指向的元素。例如,在vector中,*it 返回当前迭代器 it 指向的元素的值。

  2. 递增和递减:使用 ++ 操作符将迭代器移动到容器中的下一个元素,使用 -- 操作符将迭代器移动到容器中的上一个元素。例如,在vector中,++it 将迭代器 it 移动到下一个元素。

  3. 比较:使用 ==!=<><=>= 等操作符可以比较两个迭代器的位置关系。例如,在vector中,it1 == it2 可以判断迭代器 it1it2 是否指向同一位置。

除了基本操作外,迭代器还可以用于在容器中进行插入、删除和修改等操作。例如,在vector中,我们可以使用 insert() 函数在任意位置插入新元素,使用 erase() 函数删除指定位置的元素,并且可以通过迭代器来修改容器中的元素的值。

总结起来,迭代器是一种强大的工具,它提供了一种通用而灵活的方式来遍历和操作容器中的元素。通过迭代器,我们可以在不知道容器内部数据结构的情况下访问和修改容器中的数据,从而提高代码的可读性和可维护性。

假设我们有一个存储学生信息的vector容器,每个学生包含姓名和年龄两个属性。我们希望通过遍历容器,找到年龄最大的学生并输出其姓名和年龄信息。

#include <iostream>
#include <vector>using namespace std;struct Student {string name;int age;
};int main() {vector<Student> students = {{"Alice", 20}, {"Bob", 19}, {"Charlie", 21}, {"David", 18}};// 定义一个迭代器来指向年龄最大的学生auto maxAgeStudent = students.begin();// 遍历容器,找到年龄最大的学生for (auto it = students.begin(); it != students.end(); ++it) {if (it->age > maxAgeStudent->age) {maxAgeStudent = it;}}// 输出年龄最大的学生的姓名和年龄cout << "The oldest student is: " << maxAgeStudent->name << ", " << maxAgeStudent->age << " years old." << endl;return 0;
}

在上述代码中,我们定义了一个名为Student的结构体,用于表示学生的姓名和年龄属性。然后,我们创建了一个存储学生信息的vector容器,并初始化了几个学生对象。

接下来,我们使用迭代器遍历整个学生容器,并通过比较年龄的方式找到年龄最大的学生。在遍历过程中,我们将迭代器 maxAgeStudent 指向年龄最大的学生。

最后,我们通过解引用迭代器,输出了年龄最大的学生的姓名和年龄信息。

运行上述代码,输出将是:

The oldest student is: Charlie, 21 years old.

这个案例展示了如何使用迭代器遍历容器,并根据具体需求对容器中的元素进行操作和处理。通过迭代器,我们可以更方便地访问和操作容器中的数据,从而简化了代码的编写和维护过程。

三、使用迭代器时注意事项

当使用迭代器时,有一些注意事项需要记住:

  1. 避免迭代器失效:在对容器进行修改操作(如插入或删除元素)后,迭代器很可能会失效。如果在迭代过程中进行了修改操作,那么后续的迭代器可能无法正常工作或引发未定义行为。因此,在对容器进行修改操作之后,应该谨慎使用之前的迭代器。
  2. 小心解引用空迭代器:在使用迭代器之前,确保它不是空迭代器(指向容器之外的位置)。解引用空迭代器将导致未定义行为。
  3. 使用合适的迭代器类型:不同的容器类型有不同的迭代器类型,确保使用正确的迭代器类型来遍历和操作容器。例如,使用begin()end()来遍历大多数容器,但对于std::list,还可以使用++--操作符来移动迭代器。
  4. 迭代器失效:在使用迭代器遍历容器时,如果在遍历过程中对容器进行了插入、删除等修改操作,可能会导致迭代器失效。失效意味着迭代器不再指向有效的元素位置,进而可能导致未定义行为。为了避免这种情况,可以使用插入和删除操作后返回的新的迭代器或者使用智能迭代器(如std::list中的迭代器)。
  5. const 迭代器:对于容器中的 const 元素,应该使用 const 迭代器进行访问。例如,在 const vector 中使用 begin() 返回的是一个 const_iterator,它只能用于访问元素,而不能修改元素的值。
  6. 迭代器范围:在使用迭代器进行遍历时,要确保迭代器不会超出容器的有效范围。比如,当迭代器指向容器的最后一个元素时,对其进行递增操作将导致越界。因此,在编写代码时要小心处理迭代器的范围。
  7. 安全删除:删除容器中的元素时,要注意使用 erase() 函数返回的新的迭代器来更新迭代器,并防止迭代器失效。例如,在删除 vector 中的元素后,应该将迭代器更新为 erase() 返回的新的迭代器。
  8. 多线程安全:在多线程环境下使用迭代器时,要注意保护共享数据的访问。如果多个线程同时修改容器,可能导致迭代器失效或者产生竞争条件。可以使用互斥锁等机制来保护迭代器的访问。

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

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

相关文章

三、Qt核心与Qt类库

一、Qt核心&#xff1a;元对象系统 1、Qt核心特点 Qt对标准C进行了扩展&#xff0c;引入了一些新的概念和功能元对象编译器&#xff08;MOC&#xff09;是一个预处理器&#xff0c;先将Qt的特性程序转为标准C程序&#xff0c;再由标准C编译器进行编译Qt为C语言增加的特性在Qt…

提升开发效率:npm包管理器的使用技巧

文章目录 一、npm简介二、npm的基本操作1. 安装Node.js和npm2. 创建和管理项目3. 安装依赖4. 卸载依赖5. 更新依赖 三、npm的高级特性1. 使用不同版本的依赖项2. 查看已安装的依赖项和它们的版本信息3. 运行脚本命令 《Node.js从入门到精通&#xff08;软件开发视频大讲堂&…

09-生成器模式(Builder)模式

意图 将一个复杂对象的构建与它的表示分离&#xff0c;使得同样的构建过程可以创建不同的表示。 理解 如果构建一个对象的的过程会比较复杂&#xff0c;或者说在写代码的过程中&#xff0c;需要比较频繁地构建某个对象&#xff0c;那么可以针对这个对象写一个专门用于构建这…

2024前端炫酷源码分享(附效果图及在线演示)

分享10款非常有趣的前端特效源码 其中包含css动画特效、js原生特效、svg特效以及小游戏等 下面我会给出特效样式图或演示效果图 但你也可以点击在线预览查看源码的最终展示效果及下载源码资源 GSAP-火箭动画特效 GSAP 火箭动画 当氮气充足的情况下 火箭会冲出 并继续飞行 图片…

C#,字符串匹配算法(模式搜索)Z算法的源代码与数据可视化

Z算法也是模式搜索&#xff08;Pattern Search Algorithm&#xff09;的常用算法。 本文代码的运算效果&#xff1a; 一、Z 算法 线性时间模式搜索算法的Z算法&#xff0c;在线性时间内查找文本中模式的所有出现。 假设文本长度为 n&#xff0c;模式长度为 m&#xff0c;那么…

【Spring Cloud 】进阶之Config配置中心

目录 config大致的一个思路&#xff1a; 二&#xff0c;前期准备 2.1导入依赖 2.2编写bootstrop.yml&#xff1a; 三&#xff0c;编写Controller类 3.1获取单个配置类信息 3.2获取多个配置类信息 &#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f3…

Linux习题6

解析&#xff1a;排序必须得是rwx,所以B不对 解析&#xff1a; /etc/resolv.conf&#xff1a;是DNS配置文件。在网卡配置文件中进行配置&#xff0c;默认情况下&#xff0c;网卡配置文件DNS优于/etc/resolv.conf。 /etc/hostname&#xff1a;在centos7&#xff0c;配置主机名…

Linux时间同步和时间设置

时间分为&#xff1a; 1、hwclock&#xff1a;用于查看硬件时间 hwclock -r&#xff08;--show&#xff1a;读取硬件时钟并打印结果&#xff09; &#xff1a;查看硬件时间 hwclock -s &#xff1a;系统时间向硬件时间同步 hwclock -w &#xff1a;硬件时间向系统时间同步 …

我的第一个前端项目,vue项目从零开始创建和运行

​入门前端&#xff0c;从基础做起&#xff0c;从零开始新建项目 背景&#xff1a;VUE脚手架项目是一个“单页面”应用&#xff0c;即整个项目中只有1个网页&#xff01; 在VUE脚手架项目中&#xff0c;主要是设计各个“视图组件”&#xff0c;它们都是整个网页中某个部分&…

TypeScript 从入门到进阶之基础篇(六) 类型(断言 、推论、别名)| 联合类型 | 交叉类型

系列文章目录 TypeScript 从入门到进阶系列 TypeScript 从入门到进阶之基础篇(一) ts基础类型篇TypeScript 从入门到进阶之基础篇(二) ts进阶类型篇TypeScript 从入门到进阶之基础篇(三) 元组类型篇TypeScript 从入门到进阶之基础篇(四) symbol类型篇TypeScript 从入门到进阶…

自用PHP在线Access转html表格小功能(快速预览access)

自用PHP在线Access转html表格小功能(支持大文件上传,得到一表一文件) 本工具用于Access数据表转html下载供预览,特别适合各类程序员。 开发环境(可能只支持)Windows IIS PHP5.4 其他系统或新版本都不支持 <?php /* //自用PHP在线Access转html表格小功能(支持大文件上传,得…

一篇五分生信临床模型预测文章代码复现——Figure 10.机制及肿瘤免疫浸润(十)——Cibersort——完结

之前讲过临床模型预测的专栏,但那只是基础版本,下面我们以自噬相关基因为例子,模仿一篇五分文章,将图和代码复现出来,学会本专栏课程,可以具备发一篇五分左右文章的水平: 本专栏目录如下: Figure 1:差异表达基因及预后基因筛选(图片仅供参考) Figure 2. 生存分析,…

关于目标检测中按照比例将数据集随机划分成训练集和测试集

1. 前言 在做目标检测任务的时候&#xff0c;不少网上的数据&#xff0c;没有划分数据集&#xff0c;只是将数据和标签放在不同的文件夹下&#xff0c;没有划分数据集 虽然代码简单&#xff0c;每次重新编写还是颇为麻烦&#xff0c;这里记录一下 如下&#xff0c;有的数据集…

常见的缓存淘汰算法

FIFO、LRU、LFU 和 WindowTinyLFU 是常见的缓存淘汰算法&#xff0c;用于决定在缓存容量不足时应该如何选择要淘汰的数据。 常见的缓存淘汰算法包括&#xff1a; FIFO&#xff08;先进先出&#xff09;算法&#xff1a;按照数据最早进入缓存的顺序进行淘汰。即&#xff0c;最先…

HNU-数据库系统-实验3-数据库设计

数据库系统 课程实验3数据库设计 计科210X 甘晴void 202108010XXX 目录 文章目录 数据库系统 课程实验3<br>数据库设计实验目的实验内容实验重难点实验环境实验过程&#xff08;0&#xff09;数据库需求描述&#xff08;1&#xff09;数据库概念结构设计E-R图实体图书馆…

openGauss学习笔记-188 openGauss 数据库运维-常见故障定位案例-core问题定位

文章目录 openGauss学习笔记-188 openGauss 数据库运维-常见故障定位案例-core问题定位188.1 磁盘满故障引起的core问题188.1.1 问题现象188.1.2 原因分析188.1.3 处理办法 188.2 GUC参数log_directory设置不正确引起的core问题188.2.1 问题现象188.2.2 原因分析188.2.3 处理办…

利用ChatGLM3构建Prompt实现Text2SQL

之前使用ChatGLM3的自定义工具实现了查询MySQL数据库&#xff0c;但感觉功能还是比较受限。 https://blog.csdn.net/weixin_44455388/article/details/135270879?spm1001.2014.3001.5501 使用ChatGLM3实现Text2SQL 前言Text2SQL的构建第一阶段&#xff1a;SQL脚本构建&#xf…

软件工程_复习

软件工程 软件危机(1968 60年代) 产生软件危机的原因: 一方面与软件本身的特点有关,另一方面也和软件开发和维护的方法不正确有关。 与软件本身特点有关: 1.软件不同于硬件,软件是计算机系统中的逻辑部件,缺乏“可见性”,管理和控制软件开发过程相当困难 2.软件在运行过…

Python笔记06-文件操作

文章目录 文件的编码文件读取文件写入文件追加 文件的编码 编码技术即&#xff1a;翻译的规则&#xff0c;记录了如何将内容翻译成二进制&#xff0c;以及如何将二进制翻译回可识别内容。算机中有许多可用编码&#xff1a;UTF-8、GBK、Big5等 不同的编码&#xff0c;将内容翻译…

typescript递归处理

typescript是一种类型强约束的语言&#xff0c;一般来讲定义类型时都要明确指定类型的数据结构。而如果数据结构中涉及到不知道基层嵌套的递归时&#xff0c;就会有一些麻烦。 在 https://stackoverflow.com/questions/51657815/recursive-array-type-typescript 有一个回答…