C++ STL(1)迭代器
文章目录
- 一、迭代器详解
- 1、迭代器的定义与功能
- 2、迭代器类型
- 3、示例
- 4、迭代器失效
- 4.1、`vector` 迭代器失效分析
- 4.2、`list` 迭代器失效分析
- 4.3、`set` 与 `map` 迭代器失效分析
- 5、总结
前言:
在C++标准模板库(STL)中,迭代器是一个核心概念,它提供了一种统一的方法来访问和遍历容器中的元素,而无需关心容器的具体类型。迭代器就像是一个智能指针,封装了对容器内部元素的访问方式,使得算法能够以一致的方式操作不同的容器。
一、迭代器详解
1、迭代器的定义与功能
迭代器本质上是一个对象,它支持指针的某些操作,如访问、解引用、递增和递减等。通过迭代器,可以遍历容器中的所有元素,读取或修改它们的值,甚至可以在某些情况下连接算法与容器,实现复杂的操作。
迭代器的主要功能包括:
- 遍历容器:通过迭代器可以遍历容器中的所有元素。例如,使用
begin()
和end()
方法获取容器的起始和结束迭代器,然后通过循环来访问每个元素。 - 访问元素:可以通过迭代器读取或修改容器中的元素。这通常是通过解引用迭代器(使用
*
操作符)来实现的。 - 连接算法与容器:STL中的很多算法(如排序、查找等)都是通过迭代器来操作容器的。迭代器为算法提供了一个统一的接口,使得算法可以独立于容器的具体实现。
2、迭代器类型
STL中定义了五种主要的迭代器类型,它们提供了不同级别的功能和灵活性:
- 输入迭代器(Input Iterators):这种迭代器用于从容器中读取数据。它只支持单向遍历,即只能向前移动(通过
++
操作符)。输入迭代器只能进行一次读取,读取后迭代器就会前进到下一个元素。 - 输出迭代器(Output Iterators):与输入迭代器相反,输出迭代器用于向容器中写入数据。它同样只支持单向遍历,且只能进行一次写入操作,写入后迭代器会自动前进到下一个位置。
- 前向迭代器(Forward Iterators):前向迭代器类似于输入和输出迭代器,但它支持多次读写操作。它也只能单向遍历,但可以对同一个元素进行多次访问。
- 双向迭代器(Bidirectional Iterators):双向迭代器可以在容器中向前和向后移动。它扩展了前向迭代器的功能,使得迭代器可以使用
--
、++
操作符向前后移动。双向迭代器在像list
、set
和map
这样的容器中非常有用。不能使用类似it + n
的表达式来直接跳转到容器中的第n
个元素。 - 随机访问迭代器(Random Access Iterators):这是最强大的迭代器类型,它支持所有前面提到的迭代器的功能,并且能够进行随机访问。这意味着除了能够向前和向后移动,随机访问迭代器还能够直接跳跃到任意位置(如通过
+
或-
操作符)。vector
和deque
容器提供了随机访问迭代器。
3、示例
使用迭代器遍历并修改
std::vector
中元素,示例:
#include <iostream>
#include <vector>int main() {std::vector<int> v = {1, 2, 3, 4, 5};// 使用迭代器遍历并修改 vector 中的元素for (std::vector<int>::iterator it = v.begin(); it != v.end(); ++it) {*it *= 2; // 将每个元素的值乘以 2}// 打印修改后的 vectorfor (int val : v) {std::cout << val << " ";}std::cout << std::endl;return 0;
}
在这个例子中,我们创建了一个std::vector<int>
并初始化了它。然后,我们使用迭代器遍历了这个vector
,并通过解引用迭代器来修改每个元素的值。最后,我们打印了修改后的vector
。
4、迭代器失效
迭代器失效是STL编程中常见的问题。当容器发生变化时(如元素被删除、容器被重新分配或插入新元素等),之前获取的迭代器可能会失效,即不再指向有效的元素或不再有意义。为了避免迭代器失效导致的未定义行为,应该谨慎操作容器,并在必要时更新迭代器。
4.1、vector
迭代器失效分析
std::vector
是C++标准库中的一个序列容器,它提供了动态数组的功能。然而,在使用std::vector
的迭代器时,需要注意迭代器失效的问题。迭代器失效通常发生在容器的底层存储结构发生改变时,如扩容、插入或删除元素等。
迭代器失效的原因:
- 扩容操作: 当
std::vector
需要增加其容量以容纳更多元素时,它可能会分配一个新的更大的内存块,并将现有元素复制到新的内存块中。这个过程中,原有的内存块会被释放,因此指向原有内存块的迭代器将失效。引起扩容的操作包括:resize()、insert()、push_back()
等。 - 插入操作: 在
std::vector
中插入元素时,如果插入点之后的元素需要移动位置以腾出空间给新元素,那么插入点之后的迭代器将失效。这是因为这些迭代器现在指向的是已经被移动的元素的新位置,而不再是它们原来的位置。 - 删除操作: 使用
erase()
删除std::vector
中的元素时,删除点之后的元素会向前移动以填补被删除元素留下的空隙。虽然这不会改变底层存储结构(即不会重新分配内存),但删除点之后的迭代器仍然会失效,因为它们现在指向的是已经被移动的元素的新位置。
如何避免迭代器失效:
在进行插入、删除或扩容操作后,如果需要继续使用迭代器,应该重新获取迭代器。例如,在使用
insert()
或erase()
后,可以使用它们返回的迭代器(如果适用)或重新从容器的begin()
或end()
开始遍历。
示例:
#include <iostream>
#include <vector> int main() { std::vector<int> vec = {1, 2, 3, 4, 5}; // 使用迭代器遍历vector并删除元素 for (auto it = vec.begin(); it != vec.end(); /* 注意这里没有递增迭代器的操作 */) { if (*it % 2 == 0) { // 假设我们要删除所有偶数元素 // 使用erase删除当前元素,并获取新的迭代器 it = vec.erase(it); // erase返回删除点之后的迭代器 // 注意:此时it已经更新为指向下一个元素的迭代器,因此不需要再递增 } else { // 如果当前元素不是偶数,则递增迭代器以继续遍历 ++it; } } // 输出剩余的元素 for (int num : vec) { std::cout << num << " "; } std::cout << std::endl; return 0;
}
4.2、list
迭代器失效分析
std::list
的迭代器在大多数情况下不会因为容器的扩容或元素移动而失效。然而,std::list
的迭代器在某些操作下仍然可能失效。
迭代器失效的原因:
- 元素删除: 当使用
erase()
删除 std::list 中的元素时,指向被删除元素的迭代器会失效。这是因为erase()
操作会移除链表中的节点,而迭代器实际上是指向这些节点的指针或引用。 - 迭代器自身失效: 如果迭代器被显式地销毁或赋值为其他迭代器的值(特别是如果赋值操作导致了迭代器的复制或移动,并且原始迭代器被销毁),那么该迭代器将失效。
如何避免迭代器失效:
当使用
erase()
删除元素时,应该立即使用erase()
返回的迭代器(它指向被删除元素之后的第一个元素)来更新你的迭代器。
示例:
#include <iostream>
#include <list> int main() { std::list<int> lst = {1, 2, 3, 4, 5}; // 使用迭代器遍历list并删除元素 for (auto it = lst.begin(); it != lst.end(); /* 注意这里没有固定的递增操作位置 */) { if (*it % 2 == 0) { // 假设我们要删除所有偶数元素 it = lst.erase(it); // 使用erase删除当前元素,并更新迭代器 // 注意:此时it已经更新为指向下一个元素的迭代器(如果存在) } else { // 如果当前元素不是偶数,则递增迭代器以继续遍历 ++it; } } // 输出剩余的元素 for (int num : lst) { std::cout << num << " "; } std::cout << std::endl; return 0;
}
4.3、set
与 map
迭代器失效分析
std::map
和std::set
是两种常见的关联容器。它们基于平衡二叉树(通常是红黑树)实现,提供了高效的查找、插入和删除操作。插入新元素时不会导致已有的迭代器失效,删除元素时,只会让当前的迭代器失效,别的迭代器不受影响。但是,在遍历容器的过程如果调用erase()
函数删除元素,需要更新迭代器。当删除元素时,下面两种方法都可有效避免迭代器失效:
方法一:使用erase()
返回值更新迭代器
set<int> valset = { 1,2,3,4,5,6 };
set<int>::iterator iter;
for (iter = valset.begin(); iter != valset.end(); ){if (3 == *iter){iter = valset.erase(iter);} else {++iter;}
}
方法二:使用it ++
set<int> valset = { 1,2,3,4,5,6 };
set<int>::iterator iter;
for (iter = valset.begin(); iter != valset.end(); ){if (3 == *iter){valset.erase(iter++);} else {++iter;}
}
传给
erase()
的是iter的一个副本,iter++是下一个有效的迭代器。
5、总结
STL迭代器是C++标准模板库中的一个重要概念,它提供了一种统一的方法来访问和遍历容器中的元素。通过迭代器可以实现复杂的算法和容器操作,而无需关心容器的具体类型。了解迭代器的类型和使用方法对于编写高效、可维护的C++代码至关重要。
相关文章:
C++ STL(1)迭代器
文章目录 一、迭代器详解1、迭代器的定义与功能2、迭代器类型3、示例4、迭代器失效4.1、vector 迭代器失效分析4.2、list 迭代器失效分析4.3、set 与 map 迭代器失效分析 5、总结 前言: 在C标准模板库(STL)中,迭代器是一个核心概念…...
uview表单校验不生效问题
最近几次使用发现有时候会不生效,具体还没排查出来什么原因,先记录一下解决使用方法 <u--formlabelPosition"top"labelWidth"auto":model"form":rules"rules"ref"uForm" ><view class"…...
前端开发设计模式——单例模式
目录 一、单例模式的定义和特点: 1.定义: 2.特点: 二、单例模式的实现方式: 1.立即执行函数结合闭包实现: 2.ES6类实现: 三、单例模式的应用场景 1.全局状态管理: 2.日志记录器: …...
行情叠加量化,占据市场先机!
A股久违的3000点,最近都没有更新,现在终于对我们的市场又来点信息。相信在座的朋友这几天都是喜笑颜开,对A股又充满信心。当前行情好起来了,很多朋友又开始重回市场,研究股票学习量化,今天我们给大家重温下…...
大厂面试真题-ConcurrentHashMap怎么保证的线程安全?
ConcurrentHashMap是Java中的一个线程安全的哈希表实现,它通过一系列精妙的机制来保证线程安全。以下是ConcurrentHashMap保证线程安全的主要方式: 分段锁(Segment Locking,Java 1.8之前): 在Java 1.8之前的…...
【RabbitMQ】消息堆积、推拉模式
消息堆积 原因 消息堆积是指在消息队列中,待处理的消息数量超过了消费者处理能力,导致消息在队列中不断堆积的现象。通常有以下几种原因: 消息生产过快:在高流量或者高负载的情况下,生产者以极高的速率发送消息&…...
MySQL常用SQL语句(持续更新中)
文章目录 数据库相关表相关索引相关添加索引 编码相关系统变量相关 收录一些经常用到的sql 数据库相关 建数据库 CREATE DATABASE [IF NOT EXISTS] <数据库名> [[DEFAULT] CHARACTER SET <字符集名>] [[DEFAULT] COLLATE <校对规则名>];例如: C…...
【更新】红色文化之红色博物馆数据集(经纬度+地址)
数据简介:红色博物馆作为国家红色文化传承与爱国主义教育的重要基地,遍布全国各地,承载着丰富的革命历史与文化记忆。本数据说明旨在汇总并分析全国范围内具有代表性的红色博物馆的基本信息,包括其地址、特色及教育意义࿰…...
Python项目Flask框架整合Redis
一、在配置文件中创建Redis连接信息 二、 实现Redis配置类 import redis from config.config import REDIS_HOST, REDIS_PORT, REDIS_PASSWD, REDIS_DB, EXPIRE_TIMEclass RedisDb():def __init__(self, REDIS_HOST, REDIS_PORT, REDIS_DB, EXPIRE_TIME, REDIS_PASSWD):# 建立…...
完整网络模型训练(一)
文章目录 一、网络模型的搭建二、网络模型正确性检验三、创建网络函数 一、网络模型的搭建 以CIFAR10数据集作为训练例子 准备数据集: #因为CIFAR10是属于PRL的数据集,所以需要转化成tensor数据集 train_data torchvision.datasets.CIFAR10(root&quo…...
高效便捷,体验不一样的韩语翻译神器
嘿,大家好啊!今天想跟大家聊聊我用过的几款翻译神器,特别是它们在翻译韩语时的那些小感受。作为一个偶尔需要啃啃韩语资料或者跟韩国朋友聊天的普通人,我真心觉得这些翻译工具简直就是我的救星! 一、福昕在线翻译 网址…...
Markdown笔记管理工具Haptic
什么是 Haptic ? Haptic 是一个新的本地优先、注重隐私的开源 Markdown 笔记管理工具。它简约、轻量、高效,旨在提供您所需的一切,而不包含多余的功能。 目前官方提供了 docker 和 Mac 客户端。 Haptic 仍在积极开发中。以下是未来计划的一些…...
网络原理-传输层UDP
上集回顾: 上一篇博客中讲述了应用层如何自定义协议:确定传输信息,确定数据格式 应用层也有一些现成的协议:HTTP协议 这一篇博客中来讲述传输层协议 传输层 socket api都是传输层协议提供的(操作系统内核实现的了…...
C++中,如何使你设计的迭代器被标准算法库所支持。
iterator(读写迭代器) const_iterator(只读迭代器) reverse_iterator(反向读写迭代器) const_reverse_iterator(反向只读迭代器) 以经常介绍的_DList类为例,它的迭代…...
Java NIO 全面详解:掌握 `Path` 和 `Files` 的一切
在 Java 7 中引入的 NIO (New I/O) 为文件系统和流的操作带来了强大的能力,其中 Path 和 Files 是核心部分。Path 作为对文件路径的抽象,提供了灵活的方式处理文件系统中的路径;Files 则通过一系列静态方法,使得文件的读写、复制、…...
bluez免提协议hands-free介绍,全到无法想象,bluez hfp ag介绍
零. 前言 由于Bluez的介绍文档有限,以及对Linux 系统/驱动概念、D-Bus 通信和蓝牙协议都有要求,加上网络上其实没有一个完整的介绍Bluez系列的文档,所以不管是蓝牙初学者还是蓝牙从业人员,都有不小的难度,学习曲线也相对较陡,所以我有了这个想法,专门对Bluez做一个系统…...
关于区块链的安全和隐私
背景 区块链技术在近年来发展迅速,被认为是安全计算的突破,但其安全和隐私问题在不同应用中的部署仍处于争论焦点。 目的 对区块链的安全和隐私进行全面综述,帮助读者深入了解区块链的相关概念、属性、技术和系统。 结构 首先介绍区块链…...
特征工程——一门提高机器学习性能的艺术
当前围绕人工智能(AI)和机器学习(ML)展开的许多讨论以模型为中心,聚焦于 ML和深度学习(DL)的最新进展。这种模型优先的方法往往对用于训练这些模型的数据关注不足,甚至完全忽视。类似MLOps的领域正迅速发展,通过系统性地训练和利用ML模型&…...
Paper解读:工作场所人机协作的团队形成:促进组织变革的目标编程模型
人工智能(AI)具有降低运营成本、提高效率和改善客户体验的潜力。 因此,在组织中组建项目团队至关重要,这样他们就会在决策过程中欢迎人工智能。 当前的技术革命要求公司快速变革,并增加了对团队在促进创新采用方面的作…...
图文深入理解Oracle Network配置管理(一)
List item 本篇图文深入介绍Oracle Network配置管理。 Oracle Network概述 Oracle Net 服务 Oracle Net 监听程序 <oracle_home>/network/admin/listener.ora <oracle_home>/network/admin/sqlnet.ora建立网络连接 要建立客户机或中间层连接,Oracle…...
leetcode-链表篇3
leetcode-61 给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。 示例 1: 输入:head [1,2,3,4,5], k 2 输出:[4,5,1,2,3]示例 2: 输入:head [0,1,2], k 4 输出&#x…...
RAG(Retrieval Augmented Generation)及衍生框架:CRAG、Self-RAG与HyDe的深入探讨
近年来,随着大型语言模型(LLMs)的迅猛发展,我们在寻求更精确、更可靠的语言生成能力上取得了显著进展。其中,检索增强生成(Retrieval-Augmented Generation)作为一种创新方法,极大地…...
C语言介绍
什么是C语言 C programing language 能干什么 Hello world? 如何学C语言 no reading no learning...
损失函数篇 | YOLOv10 更换损失函数之 MPDIoU | 《2023 一种用于高效准确的边界框回归的损失函数》
论文地址:https://arxiv.org/pdf/2307.07662v1.pdf 边界框回归(Bounding Box Regression,BBR)在目标检测和实例分割中得到了广泛应用,是目标定位的重要步骤。然而,对于边界框回归的大多数现有损失函数来说,当预测的边界框与真值边界框具有相同的长宽比,但宽度和高度的…...
WMware安装WMware Tools(Linux~Ubuntu)
1、这里终端里面输入sudo apt upgrade用于更新最新的包 sudo apt upgrade 2、安装 open-vm-tools-desktop 包, Ps:这里是以为我已经安装好了。 udo apt install open-vm-tools-desktop -y3、最后重启就大功告成了 reboot 4、测试是否成功:…...
SLAM ORB-SLAM2(30)关键帧跟踪
SLAM ORB-SLAM2(30)关键帧跟踪 1. 关键帧跟踪2. TrackReferenceKeyFrame2.1. 将当前普通帧的描述子转化为BoW向量2.2. 通过词袋BoW加速当前帧与参考帧之间的特征点匹配2.3. 将上一帧的位姿态作为当前帧位姿的初始值2.4. 通过优化3D-2D的重投影误差来获得位姿2.5. 剔除优化后的…...
k8s 部署 prometheus
创建namespace prometheus-namespace.yaml apiVersion: v1 kind: Namespace metadata:name: ns-prometheus拉取镜像 docker pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/quay.io/prometheus/prometheus:v2.54.0prometheus配置文件configmap prometheus-configmap.yaml …...
使用VBA快速生成Excel工作表非连续列图片快照
Excel中示例数据如下图所示。 现在需要拷贝A2:A15,D2:D15,J2:J15,L2:L15,R2:R15为图片,然后粘贴到A18单元格,如下图所示。 大家都知道VBA中Range对象有CopyPicture方法可以拷贝为图片,但是如果Range对象为非连续区域,那么将产生10…...
解决GitHub下载速度慢
解决GitHub下载速度慢 方法一:使用git clone 地址 --depth 1来下载 depth 1 表示只科隆最新的一次提交,也就是默认主分支,而不是完整地克隆整个代码仓库,这样可以减少下载地数据,加快克隆操作 可以用git clone 地址 …...
【机器学习(五)】分类和回归任务-AdaBoost算法
文章目录 一、算法概念一、算法原理(一)分类算法基本思路1、训练集和权重初始化2、弱分类器的加权误差3、弱分类器的权重4、Adaboost 分类损失函数5、样本权重更新6、AdaBoost 的强分类器 (二)回归算法基本思路1、最大误差的计算2…...
aspcms网站地图/百度知道问答首页
骁龙780G:搭载全新的5nm制作工艺,为用户提供很好的手机旗舰功耗管理 我用的手机就是活动时8折抢购的 点击开抢http://shouji.adiannao.cn/7 骁龙778G:搭载6nm制作工艺,这是目前性价比很好的芯片制作工艺 骁龙780G:在芯…...
华为网站建站/网上代写文章一般多少钱
之前编译的参数没有添加mysqli支持,因代码需要,必须添加上去。这次尝试一下扩展编译。 由于是源代码安装的,所以在php的目录bin下面有相关的命令。 到解压的源代码的ext目录下面,进入mysqli目录,执行/home/php/bin/php…...
高职图书馆网站建设大赛/产品营销策略有哪些
一、申请条件(以下各条必须同时满足)1、完成硕士阶段全部课程学习,且成绩优良。2、外语水平优秀:外语成绩应获得全国大学英语六级460分及以上,或托福机考80分以上,或雅思≥5.5以上(有效期5年,即2010年12月及以后的成绩…...
自己做的网站怎么上传到域名/如何在手机上开自己的网站
文 | 曾响铃 来源 | 科技向令说(xiangling0815) 众所周知,在经济技术全球化的今天,标准体系已经逐渐成为国际产业发展中的关键因素,谁能主导标准制定,谁就能成为信息时代全球企业竞争的优势方。 而最近&am…...
热门的网页设计工具有哪些/厦门百度快照优化排名
废话不多说,直接开始,整体规划如下: 实验通过虚拟机实现,基于Red Hat 5.8来完成 1.资源分析 在做实验之前,首先要知道高可用用于分配的资源有哪些,由于我们做的是Lvs DR模型Director的高可用,用…...
苏州市城市建设局网站/搜索引擎排名优化是什么意思
今天我们继续来学习PERFORMANCE MONITORING AND STATISTICS(性能监测与统计),今天学习的是什么命令呢,那就是dmidecode(通过BIOS查看硬件信息) Ready Go!!! 老规矩 dmidecode --help -d:(def…...