C++相关概念和易错语法(12)(迭代器、string容量调整)

news2024/11/17 9:52:08

1.迭代器(以string为例)

(1)基本理解:在我们刚接触迭代器的时候,我们可以将迭代器理解为改造过的“指针”,这是一个新的类型,指向对应容器中的各个元素。我们可以像指针那样对迭代器进行++,*等操作,只不过++是指向下一个元素而非下一个字节,*得到的是对应的元素而非一个字节的内容。我们发现虽然迭代器并不能完全和指针划等号,但是它们的功能基本相同,而且在迭代器更安全、方便,支持所有容器,因此它是主流、通用的访问方式。

(2)begin、end:

begin和end是对应类的成员函数,在不同容器有不同的实现方法。

要得到对应容器的迭代器,我们需要调用实例化对象的成员函数。

80fb69a5e851411f892dbf0cec8363e3.png

迭代器在不同的容器里面访问的大小、方式都有所区别,因此迭代器是根据不同容器设计的,所以注意迭代器类型前面要确定类域,写作string::iterator

同样我们也可以获取末尾元素(有效字符)的下一个元素\0的迭代器

注意左闭右开的规则,不要越界访问,虽然我们知道\0也是字符串的一部分,本质上说也不算越界,但是考虑到实际使用没正常人会去对这个\0动手脚(如果单独改了这个\0,就会导致字符串没有\0,会引发一系列隐患),所以只要访问\0或者越界,就会断言。

(3)范围for的运用

利用迭代器,我们可以很轻松的访问对象里面的数据,就像指针一样。

但我们还有其它更简洁的方法。

C++借鉴了其它语言的范围for用法,使用for (type e : arr)可以快速遍历数组,不会发生越界,也不需要自己去算数组的大小,很方便。范围for的实现本质上是迭代器,遍历的时候是自动调用函数begin得到初始位置的迭代器并“解引用”,自动++直到和end迭代器相同为止,这也是范围for知道从哪里开始,从哪里结束的原因。因此我们可以应用于string中,实现快速遍历。

这里值得注意的是,我们得到迭代器后可以对对应的数据进行修改,这并没有影响封装的特性,因为迭代器本身就是类里面定义出来的,修改数据的手段受到迭代器本身的限制(不能随便针对某个字节进行修改,只能对有效部分的数据修改),数据方法集为一体。

注意要使用引用才能修改,否则e是临时变量

而相对应的,c_str得到的就是string的地址,我们不能修改解引用的值,因为这个时候如何修改完全不受控制,会影响封装的特性。

(4)iterator begin() 和 const_iterator begin() const 的区别

我们要注意,迭代器根据访问权限的区别分为了iterator和const_iterator,这和指针一样,限制在于加了const的迭代器没有办法进行解引用再修改值的操作,也就是只读不写。一般当我们使用const string实例化对象的时候就只能用const_iterator,其调用的所有成员函数后面都要有const修饰(修饰的是this指针)

其中s.end()会去自动调用匹配const_iterator end() const,原因在于end成员函数构成了函数重载,会根据this的类型去自动匹配合适的。

​​​​​​​但是注意有无const修饰的迭代器之间不能隐式类型转换。如果接收返回值的迭代器类型错误的话,会报错。

可能还有人会混淆const_iterator和const iterator。const iterator修饰的是iterator,即不能修改iterator本身,那么迭代器本身就失去了意义,所以没有这种迭代器。const_iterator修饰的是iterator解引用后的值,不能修改。这个区别和指针的const规则类似,只不过指针是根据const和*的相对位置来区分的,迭代器iterator就一个单词,不存在相对位置的概念,所以使用const_放在iterator前面表示区分。

(5)反向迭代器

反向迭代器和正向迭代器的主要区别在于反向迭代器是用于从后向前遍历的。

当我们用rbegin时,得到的是串中最后一个有效字符(不包含\0)

而rend返回的是串中第一个字符的前一个理论字符的迭代器(这个字符不存在,是假设出来的,这里实际上已经越界了,和end有区别)

值得注意的是返回的迭代器类型是反向的,和正向的不相通

反向迭代器的其它特性和正向迭代器的相同,都存在const修饰问题。即返回值reverse_iterator和const_reverse_iterator,这里就不重复讲它们的区别了。

但是反向迭代器不能直接支持范围for,范围for自动调用的是正向迭代器,即从前向后遍历。

我们只有自己手动实现从后向前遍历。

在这里我们也可以看到正反迭代器之间的区别。当我们++时,反向迭代器的变化相当于正向迭代器的--

2.扩容

当我们要读取整个文件的字符并把它存到string中时,我们发现如果什么都不处理,默认情况下string会进行多次扩容,扩容意味着多次移动数据,涉及多次数据复制,大大影响了性能。所以在有预见的情况下,我们可以手动扩容,一次性申请大一点的空间,这样挪动数据的消耗就很小。

​​​​​​​(1)capacity、size

要理解扩容,我们需要对capacity、size有一定了解。

当我们创建string对象时,capacity和size也随之生成,这和顺序表一致,当我们存入数据时,size会增加,数据超过一定量时,会出现扩容。扩容的时候capacity也会随之变大。

注意size指向的是\0对应的下标,也就是有效数据的下一个,capacity也是指有效空间,但它其实多开辟了一个用来存\0

当使用迭代器的时候,就会受到size的限制,当迭代器指向的数据下标大于等于size对应的值时,就会判定为越界,等于size时指向的就是\0

和顺序表一样,capacity表示的是实际开辟的空间-1(有效空间,为\0预留一个字节),但是超过size的就无法访问

(2)reserve

reserve就是提前开辟空间,修改capacity的函数,它的好处在于一次性就开辟这么多空间,capacity不会再轻易地变化了。也就是说对数据的转移会减少,能有效提高程序效率。

你会发现,capacity实际的大小不是1000,这是编译器自己的处理,我们用去过分关心。

但是提前开辟空间并不代表这块空间能够被访问。虽然我们看到capacity变大了,但size并不会改变,迭代器的访问范围依旧限制在扩容前的范围内。

(3)resize

resize也是提前开辟空间的一个函数,但是它和reserve有本质区别。reserve是预开辟空间,这块空间不能被访问,不会对现有的串造成影响,访问范围也不会改变。

但resize在开辟空间,修改capacity后,还会修改size,直接扩充了我们访问的范围。

我们发现扩容后,size直接跳到100,意味着0~99的数据都能被正常访问,在默认情况下,扩容后的空位补\0,你也可以指定字符。

用resize还是reserve要根据具体情况具体分析,resize用于扩容的时候要慎用,因为它的参数的意思是将string扩充到n个字节而不是预开辟n个字节,之后填充数据是直接从size开始,这很容易出现浪费空间的情况。

3.缩容

(1)缩容的话不推荐使用reserve,在有的编译器低下什么事都不会做

(2)resize能缩容,是将多余的数据直接抛弃,将size定位到设置的值

当缩容时,resize后的第二参数没有意义

(3)shrink_to_fit

这个函数是将capacity往下减少但不改变原有数据和size,防止空间开辟了太多占着不用。

但是这个函数本质上是用时间换空间,看似只修改了capacity,实际上这还涉及空间的归还,数据挪动,很浪费资源,所以一般不要用。

我们可以在reserve开辟过多的情况下使用shrink_to_fit调整

我们还能知道,resize浪费的空间无法通过shrink_to_fit来释放,所以一定要注意resize扩容的操作

​​​​​​​

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

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

相关文章

朋友圈刷屏的粘土风格照片,你体验过了吗?

Remini 的粘土风格真的丑萌丑萌的! 从去年“妙鸭相机”的走红,到今年Remini的刷屏,其实可以看出大众对于图片趣玩的兴趣非常大! 一张普通的照片经过工具的处理,一下子变成新风格,让人眼前一亮。如果你也对…

【代码分享】使用HTML5的Canvas绘制编码说明图片

最急在工作中遇到一个需求,根据给定的编码生成编码说明,像下面这样的效果。 不同含义的编码用横杠分割,然后每个编码下面用箭头指明具体的含义。下面是我使用canvas实现的代码。具体的编码宽度大家可以根据实际情况进行调整,目前…

Excel如何设置密码保护【图文详情】

文章目录 前言一、Excel如何设置密码保护?二、Excel如何取消密码保护?总结 前言 在软件项目开发过程中,会输出很多技术文档,其中也包括保密级别很高的服务器账号Excel文档。为了确保服务器账号相关的Excel文档的安全性&#xff0…

Python经典案例爬取豆瓣Top250电影数据

随着网络数据的日益丰富,如何从海量的信息中快速、准确地提取出有价值的数据,成为了许多开发者和技术爱好者关注的焦点。在这个过程中,网络爬虫技术凭借其强大的数据获取能力,成为了数据分析和挖掘的重要工具。本文将通过一个经典…

二叉树进阶 --- 上

目录 1. 二叉搜索树的概念及结构 1.1. 二叉搜索树的概念 1.2. 二叉搜索树的结构样例 2. 二叉搜索树的实现 2.1. insert 的非递归实现 2.2. find 的非递归实现 2.3. erase 的非递归实现 2.3.1. 第一种情况:所删除的节点的左孩子为空 2.3.1.1. 错误的代码 2…

[QNX] BSP 网络性能优化:调优io-pkt和ClockPeriod提升网速

0 概要 本文介绍如何在QNX系统上优化网络性能,主要通过调整io-pkt和ClockPeriod参数来实现。通过优化,网络吞吐量可以得到显著提升。 1 优化方法 1.1 调整io-pkt的mclbytes参数: io-pkt是QNX系统中常用的网络协议栈,其mclbytes参数指定了…

一、精准化测试介绍

精准化测试介绍 一、精准化测试是什么?二、什么是代码插桩?三、两种插桩方式Offine模式:On-the-fly插桩: 四、jacoco覆盖率报告展示五、增量代码覆盖率监控原理六、精准测试系统架构图七、全量与增量覆盖率报告包维度对比八、全量与增量覆盖率…

视频断点上传

什么是断点续传 通常视频文件都比较大,所以对于媒资系统上传文件的需求要满足大文件的上传要求。http协议本身对上传文件大小没有限制,但是客户的网络环境质量、电脑硬件环境等参差不齐,如果一个大文件快上传完了网断了没有上传完成&#xf…

分布式事务?哪几种方式实现?一文看懂!

什么是分布式事务 分布式事务是指在分布式系统中涉及到多个数据库或多个应用程序之间的事务处理,这些数据库或应用程序可能分布在不同的物理节点上,甚至可能位于不同的地理位置。在分布式事务中,需要确保所有参与者的事务操作都能够保持一致性…

SNMPv3-原理浅谈+报文示例+简易配置

个人认为,理解报文就理解了协议。通过报文中的字段可以理解协议在交互过程中相关传递的信息,更加便于理解协议。 因此本文将在 SNMPv3 协议报文的基础上进行介绍。 SNMPv3 相关 RFC 文档。 关于 SNMPv3 的基本内容介绍,可参考RFC3410-Intro…

vue3中如何更优雅的使用echarts?

echarts在vue或者react中使用存在的问题 每个图表需要从头到尾写地一遍完整的option配置,这样一来的话就会显得十分的冗余在同一个项目中,其实不难发现各类图表设计十分相似,甚至是相同,因此我们没必要一直做重复的工作&#xff…

2.2、Gitea忘记密码重置密码

忘记密码后,管理员可以使用gitea的主程序输入命令重置密码。 gitea admin user change-password --username myname --password asecurepassword

Python多线程与互斥锁模拟抢购余票的示例

一、示例代码: from threading import Thread from threading import Lock import timen 100 # 共100张票def task():global nmutex.acquire() # 上锁temp ntime.sleep(0.1)n temp - 1print(购票成…

树的基本介绍

引入 定义 表示 相关概念 结点:数据元素与指向分支的指针两部分组成 树的深度:树中结点的最大层次 将树A结点(根结点)去掉,树A就变成了森林 区别 实现

vuex核心概念-actions

目录 一、概述 二、应用场景 三、使用步骤 三、注意 四、辅助函数-mapActions 一、概述 目标:明确actions的基本语法,处理异步操作。 需求:一秒钟之后,修改state的count成666。 说明:mutations必须是同步的(便于…

Softing工业推出的edgeConnector将Allen-Bradley控制器集成到工业边缘应用中

2024年4月17日(哈尔),Softing宣布扩展其基于Docker的edgeConnector产品系列,推出了新软件模块edgeConnector Allen Bradley PLC,可方便用户访问来自ControlLogix和CompactLogix控制器数据。 (edgeConnector…

【小红书采集工具】根据搜索关键词批量采集小红书笔记,含笔记正文、笔记链接、发布时间、转评赞藏等

一、背景介绍 1.1 爬取目标 熟悉我的小伙伴都了解,我之前开发过2款软件: 【GUI软件】小红书搜索结果批量采集,支持多个关键词同时抓取! 【GUI软件】小红书详情数据批量采集,含笔记内容、转评赞藏等,支持…

从诊室到云端:医疗大模型的应用挑战与未来探索

从诊室到云端:医疗大模型的应用挑战与未来探索 2023年是中国医疗大模型发展的元年,各种医疗大模型已广泛应用于临床辅助决策、医学研究、健康管理等多个场景。未来,医疗大模型有望实现多模态AI与医疗实践全流程的深入链接,应用于医…

LibreNMS简介

目录 1 LibreNMS简单介绍1.1 LibreNMS介绍 2 安装2.1 Ubuntu安装1、安装依赖2、添加 librenms 用户3、下载 LibreNMS4、设置权限5、安装 PHP 依赖项6、设置时区7、配置 MariaDB8、配置 PHP-FPM9、配置 Web 服务器10、启用 lnms 命令11、配置 snmpd12、cron13、启用调度程序14、…

OS复习笔记ch5-2

引言 在上一篇笔记中,我们介绍到了进程同步和进程互斥,以及用硬件层面上的三种方法分别实现进程互斥。其实,软件层面上也有四种方法,但是这些方法大部分都存在着一些问题: “上锁”与“检查”是非原子操作&#xff0…