C++STL的迭代器(iterator)

一、定义

        迭代器是一种检查容器内元素并且遍历容器内元素的数据类型

        【引用自:C++迭代器(iterator)_c++ iterator_NiUoW的博客-CSDN博客】迭代器是一个变量,相当于容器和操纵容器的算法之间的中介。C++更趋向于使用迭代器而不是数组下标操作,因为标准库为每一种标准容器(如vector、map和list等)定义了一种迭代器类型,而只有少数容器(如vector)支持数组下标操作访问容器元素。可以通过迭代器指向你想访问容器的元素地址,通过*x打印出元素值。这和我们所熟知的指针极其类似。

        C语言有指针,指针用起来十分灵活高效。C++语言有迭代器,迭代器相对于指针而言功能更为丰富。

        vector,是数组实现的,也就是说,只要知道数组的首地址,就能访问到后面的元素。所以,我们可以通过访问vector的迭代器来遍历vector容器元素。
        List,是链表实现的,我们知道,链表的元素都存储在一段不是连续的地址空间中。我们需要通过next指针来访问下一个元素。那么,我们也可以通过访问list的迭代器来实现遍历list容器元素。

        由此可见,迭代器和容器是密不可分的、紧密相连的的关系。不同的容器,它们的迭代器也是不同的,但是它们的迭代器功能是一样的。假如没有迭代器,由于vector和list容器的存储特点,你需要两种算法去实现遍历vector和list容器的功能,复杂且低效。有了迭代器,遍历容器的效率会大大提高。

二、为什么要使用迭代器

         使用STL(Standard Template Library)中的迭代器有以下几个好处:

1. 统一的访问方式:STL的迭代器提供了一种统一的访问容器元素的方式,无论是数组、链表、集合还是映射,都可以通过相同的迭代器接口进行遍历和访问。这种统一性简化了代码的书写,并提高了代码的可读性和可维护性。

2. 安全的访问操作:迭代器在设计上考虑了容器的边界情况,确保不会越界访问或访问非法内存引起崩溃。迭代器提供了递增、递减等操作符,使得在容器中前进或后退一个位置变得简单和安全。

3. 灵活的遍历方式:迭代器支持正向遍历、反向遍历以及跳跃式遍历等方式,使得在不同的情况下选择合适的遍历方式变得方便。比如,可以使用反向迭代器从容器的末尾向前遍历,或者使用跳跃式迭代器按照一定规则跳过一些元素。

4. 可算法化处理:STL提供了丰富的算法,如排序、查找、拷贝、删除等,这些算法可以直接操作迭代器,而不需要关心具体容器的实现。使用迭代器作为算法的参数,使得代码可复用性更强,可以将同一套算法应用于不同类型的容器。

5. 可组合的操作:迭代器的操作是可以组合的,可以在不同的操作之间进行链式调用,形成更复杂的操作序列。这种可组合性使得代码更加灵活,可以根据需求自由组合和定制迭代器操作,实现更多样化的功能。

        总之,STL中的迭代器提供了一种抽象的、统一的访问容器元素的方式,使得我们可以以一种通用的方式处理各种不同类型的容器。这样做可以提高代码的重用性、可读性和可维护性,同时还能够充分利用STL提供的丰富算法,简化开发过程并提高效率。

另一种解释:【取自C++STL之迭代器(iterator)详解_c++迭代器-CSDN博客】

(1) STL提供每种容器的实现原理各不相同,如果没有迭代器我们需要记住每一种容器中对象的访问方法,很显然这样会变得非常麻烦。

(2) 每个容器中都实现了一个迭代器用于对容器中对象的访问,虽然每个容器中的迭代器的实现方式不一样,但是对于用户来说操作方法是一致的,也就说通过迭代器统一了对所有容器的访问方式。

(3) 迭代器的使用可以提高编程的效率。

三、迭代器的使用

3.1 基本使用方法

(1) 首先要定义一个迭代器类型变量(这里以vector容器为例)。
定义方法如下:容器类名::iterator 迭代器名;
如要定义vector容器的迭代器:vector<int>::iterator iter;(这里的iter是变量名,可以自定义)
(2) 接下来要利用迭代器访问容器数据
先要了解几个成员函数,如下表所示。

成员函数功能
begin()返回指向容器中第一个元素的正向迭代器;如果是 const 类型容器,在该函数返回的是常量正向选代器。
end()返回指向容器最后一个元素之后一个位置的正向迭代器,如果是 onst 类型容器,在该函数返回的是常量正向迭代器。此函数通常和 begin() 搭配使用。
rbegin()返回指向最后一个元素的反向迭代器,如果是 const 类型容器,在该函数返回的是常量反向迭代器。
rend()返回指向第一个元素之前一个位置的反向迭代器。如果是 const 类型容器,在该函数返回的是常量反向迭代器。此函数通常和 begin() 搭配使甲。

这里的 end()、rend() 函数要注意,不是指向容器最后一个元素,而是后一个位置(看图) 

 (3) 示例

#include<iostream>
#include<vector>int main() {std::vector <int> vec; // 定义向量对象vecvec.push_back(2);vec.push_back(3);vec.push_back(5);vec.push_back(9);// 至此,向量vec中包含四个元素,分别是2,3,5,9std::vector<int>::iterator iter; // 定义迭代器类型变量iteriter = vec.begin(); // 变量被赋值为指向第一个元素的迭代器std::cout << *iter << std::endl;iter++; // 可以用自增操作,让iter指向下一个元素std::cout << *iter << std::endl;iter = vec.begin() + 2; // 让iter指向容器中的第三个位置std::cout << *iter << std::endl;
}

输出结果:
2 3 5  

注意:vector容器迭代器属于随机访问迭代器,可以一次移动多个位置,如iter=v1.begin()+2;
也可以用iter=iter+2;

3.2 容器数据的遍历

3.2.1 常见方法(正序遍历)

for (auto it = container.begin(); it != container.end(); ++it) {// process element *it
}

3.2.2 常见方法(逆序遍历) 

for (auto it = container.rbegin(); it != container.rend(); ++it) {// process element *it
}

        其中,auto是C++11的关键字,它可以自动推导迭代器类型。循环中,首先使用begin()函数获取容器起始位置的迭代器,然后每次使用递增运算符前进一个位置,直到迭代器等于end()函数返回的迭代器时结束循环。

3.2.3 注意问题 

        需要注意的是,在处理空容器或只有一个元素的容器时,begin()end()函数返回的迭代器是相同的,因此在循环中不能使用!=运算符进行比较,而应该使用    或   运算符判断是否越界。

        当一个容器为空或只有一个元素时,`begin()`和`end()`函数返回的迭代器是同一个位置,因此使用`!=`运算符进行比较可能会得到错误的结果。

        对于空容器,`begin()`和`end()`函数都返回指向末尾的迭代器,因为没有元素可以遍历。这种情况下,应该直接判断迭代器是否等于末尾迭代器,如下所示:

std::vector<int> v;
if (v.begin() == v.end()) {// 处理空容器的情况
}

        对于只有一个元素的容器,`begin()`和`end()`函数虽然会返回不同的迭代器,但是它们指向的是同一个位置,即容器中唯一的元素。这种情况下,应该使用`<`或`>`运算符进行比较,如下所示:

std::vector<int> v{1};
for (auto it = v.begin(); it < v.end(); ++it) { // 注意这里使用<std::cout << *it << std::endl;
}

        同样地,在循环中也可以使用`>=`或`<=`运算符判断是否越界,但是更好的做法是使用标准库提供的迭代器判等函数`std::equal()`、`std::lexicographical_compare()`等,这些函数会自动处理空容器和只有一个元素的容器的情况,并提供更好的可读性和代码健壮性。

3.2.4 遍历应用示例

#include<iostream>
#include<vector>int main() {std::vector <int> vec; // 定义向量对象vecvec.push_back(2);vec.push_back(3);vec.push_back(5);vec.push_back(9);// 至此,向量vec中包含四个元素,分别是2,3,5,9// 遍历向量vec中的所有元素for (auto iter = vec.begin(); iter != vec.end(); iter++) {std::cout << *iter << " ";}std:: cout << std::endl;
}

注意:上面说到end()函数是指向容器的最后一个元素的后一个位置,所以当迭代器指向最后的后一个位置时结束遍历,便可以访问所有容器元素。  

输出结果:

2 3 5 9 

四、不同容器的迭代器(iterator)的功能

vector                  随机访问
deque                  随机访问
list                        双向
set / multiset        双向
map / multimap    双向
stack                    不支持迭代器
queue                  不支持迭代器
priority_queue     不支持迭代器
 

参考文献

C++STL之迭代器(iterator)详解_c++迭代器-CSDN博客
C++迭代器(iterator)_c++ iterator_NiUoW的博客-CSDN博客
关于迭代器失效的几种情况-CSDN博客(值得阅读)

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

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

相关文章

makesense在线yolov5标注

文章目录 一、创建图片文件夹和label.txt二、在线标注数据 参考文章博主&#xff1a;风吹落叶花飘荡 一、创建图片文件夹和label.txt 创建一个放置图片的文件夹images&#xff0c;存放需要标注的图片&#xff08;图片最好重命名为1,2,3…避免后面混淆&#xff09; 创建label.t…

在软件测试行业这种情况下,凭什么他能拿25k?我却约面试都难?

在当今竞争激烈的软件测试行业中&#xff0c;近期的招聘市场确实面临一些挑战。大量的求职者争相涌入岗位&#xff0c;许多热衷于功能测试的人士甚至难以找到理想的工作机会。更不幸的是&#xff0c;连自动化测试和性能测试这些专业领域也受到了测试开发人员的竞争压力。然而&a…

整理MongoDB文档:身份验证

整理MongoDB文档:身份验证 个人博客&#xff0c;求关注。 文章概叙 本文主要讲MongoDB在单机状态下的账户配置。理解了MongoDB的语法&#xff0c;对于如何配置用户权限会知道怎么配置&#xff0c;但是请注意给谁配置什么权限才是最重要的。 最小权限原则 系统的每个程序或者…

kubernetes(2)

pod管理 应用部署 上传测试镜像 [rootk8s1 docker]# docker push reg.westos.org/library/myapp:v1 [rootk8s1 docker]# docker push reg.westos.org/library/myapp:v2创建自助式pod&#xff08;生产不推荐&#xff09; [rootk8s2 ~]# kubectl run demo --imagemyapp:v1[ro…

uniapp 安装 u-view 组件库

u-view 组件库安装教程&#xff1a;https://uviewui.com/components/install.html 注&#xff1a;以下使用 HBuilderx 安装 u-view 2.0 版本&#xff0c;不适用于其它版本。 1.安装 u-view 组件库 2、注册并登录 HBuilderx 账号&#xff0c;点击下载 u-view 组件库。 3、点击…

如何开发一个 Safari 插件

本文字数&#xff1a;2493字 预计阅读时间&#xff1a;15分钟 由于常用浏览器是Safari&#xff0c;而Safari浏览器的插件比不上Chrome&#xff0c;所以就有了自己开发常用的Safari插件的想法。 打算开发当前页面生成二维码的Extension&#xff0c;因为网络原因&#xff0c;AirD…

真实感受:是智能家居在选择合适的技术!

科技从来都是为了让我们的生活更加的简单、舒适&#xff0c;而智能家居的智能&#xff0c;体现在如何更更更方便的使用我需要控制的家居。 例如&#xff1a;下班躺在床上想休息&#xff0c;房间和大厅的灯还开着&#xff0c;这时你会选择什么产品躺着解决问题&#xff1f; 红外…

Hadoop3教程(二十八):(生产调优篇)NN、DN的多目录配置及磁盘间数据均衡

文章目录 &#xff08;148&#xff09;NN多目录配置&#xff08;149&#xff09;DataNode多目录配置及磁盘间数据平衡磁盘间数据均衡 参考文献 &#xff08;148&#xff09;NN多目录配置 NN多目录的意思是&#xff0c;本地目录可以配置成多个&#xff0c;且每个目录存放内容相…

20款VS Code实用插件推荐

前言&#xff1a; VS Code是一个轻量级但功能强大的源代码编辑器&#xff0c;轻量级指的是下载下来的VS Code其实就是一个简单的编辑器&#xff0c;强大指的是支持多种语言的环境插件拓展&#xff0c;也正是因为这种支持插件式安装环境开发让VS Code成为了开发语言工具中的霸主…

【数据结构】八大排序

目录 1. 排序的概念及其作用 1.1 排序的概念 1.2 排序运用 1.3 常见的排序算法 2. 常见排序算法的实现 2.1 插入排序 2.1.1 基本思想 2.1.2 直接插入排序 2.1.3 希尔排序&#xff08;缩小增量排序&#xff09; 2.2 选择排序 2.2.1 基本思想 2.2.2 直接选择排序 2.2…

Linux下Samba服务安装及启用全攻略

Linux下Samba服务安装及启用全攻略 前言一、安装SSH Server二、安装Samba Server1.安装net-tool2.建立账号的samba3.windows通过Samba与linux共享文件4.使用远程工具登录Linux 总结 前言 提示&#xff1a;本文详解了在Linux系统下如何安装和启用Samba服务&#xff0c;涵盖了从…

【2023年11月第四版教材】软考高项极限冲刺篇笔记(2)

1 我们要知道的事 1、考试的选择题不会出假大空的管理,一般较为具体 2.3 信息系统治理 首先治理的目标是什么 治理的管理层分为三层 原则:简单透明适合 COBIT IT审计范围:总体、组织、物理、逻辑、其他 IT审计风险:固有、控制、检查、总体审计 IT审计方法:访谈、调查、…

【微服务 SpringCloudAlibaba】实用篇 · Nacos注册中心

微服务&#xff08;5&#xff09; 文章目录 微服务&#xff08;5&#xff09;1. 认识和安装Nacos2. 服务注册到nacos和拉取服务1&#xff09;引入依赖2&#xff09;配置nacos地址3&#xff09;重启 3. 服务分级存储模型3.1 给user-service配置集群3.2 同集群优先的负载均衡 4. …

vue el-dialog弹出框自定义指令实现拖拽改变位置-宽度-高度

前言 在实际开发中我们经常使用el-dialog弹出框做表单&#xff0c;一般情况都是居中。遮挡到了一部分数据 当我们想要查看弹出框下面的数据时&#xff0c;就只能先把弹出框关闭&#xff0c;查看完数据之后在打开弹框 我们通过动态样式&#xff0c;和鼠标事件就可以实现。但自…

effective c++学习笔记(后四章)

六 继承与面向对象设计 红色字 \color{FF0000}{红色字} 红色字 32 确定你的public继承塑模出 is-a关系 如果你令class D (“Derived”)以public形式继承class B (“Base”)&#xff0c;你便是告诉C编译器&#xff08;以及你的代码读者&#xff09;说&#xff0c;每一个类型为…

Origami Studio for Mac:塑造未来,掌握原型设计之巅

在当今高度竞争的设计领域&#xff0c;原型设计的重要性不言而喻。它不仅是沟通想法&#xff0c;也是测试和改进设计的关键环节。而现在&#xff0c;一款强大的原型设计工具——Origami Studio for Mac&#xff0c;正在席卷设计界&#xff0c;以其独特的功能和卓越的性能&#…

shell变量

shell变量之学习笔记 Shell变量概念1 shell变量分类&#xff1a;2 变量的赋值3 变量赋值格式&#xff1a;4 变量命名方式5 变量声明6 变量引用7 变量清除8 变量只读9 内部参数变量10 位置参数变量11 退出和返回状态12 命令替换13 read命令14 字符串长度与截取15 字符串替换16 变…

Spring Security—Servlet 应用架构

目录 一、Filter&#xff08;过滤器&#xff09;回顾 二、DelegatingFilterProxy 三、FilterChainProxy 四、SecurityFilterChain 五、Security Filter 六、打印出 Security Filter 七、添加自定义 Filter 到 Filter Chain 八、处理 Security 异常 九、保存认证之间的…

C语言【文件】

目录 概念 文件名 文件的打开和关闭 fopen fclose 输入输出函数 fputc fgetc fputs fgets fprintf fscanf fwrite fread 三种流 scanf和sprintf 结构体转化 ​编辑 文件的随机读写 fseek ftell rewind 文本文件和二进制文件 文件读取结束的判定 文件缓冲…

C++标准模板(STL)- 类型支持 (运行时类型识别,type_info )

运行时类型识别 定义于头文件 <typeinfo> 含有某个类型的信息&#xff0c;由实现生成。​​这是 typeid 运算符所返回的类。 std::type_info 定义于头文件 <typeinfo> class type_info; 类 type_info 保有一个类型的实现指定信息&#xff0c;包括类型的名称和…