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

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扩容的操作

​​​​​​​

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

算法详解——回溯法

一、回溯法概述——问题背景 回溯法是一种解决约束满足问题的方法,特别适用于解决组合问题、搜索优化问题等。它通过逐步构建候选解决方案并且在这个解决方案不再可能满足约束或条件时进行剪枝和回溯。具体来说,回溯法可以应用于以下类型的问题&#xff…

Windows10搭建GPU版Darknet—yolov4—VS2022+CUDA+CUDNN(亲测有效)

1 VS2019安装 网址:Visual Studio: 面向软件开发人员和 Teams 的 IDE 和代码编辑器 下载完成之后双击.exe文件 步骤严格如下安装 默认语音包为中文(简体) 安装位置可以自行选择,完成以后就可以点击安装了。 安装完毕以后需要重启…

如何设置cPanel的自动备份

近期我们购买了Hostease美国VPS云主机产品,由于需要设置服务器的自动备份,我们向Hostease技术团队进行了咨询,他们提到VPS云主机的cPanel面板包含自动备份功能,下面我们就介绍如何进行自动备份的设置。 首先你需要登录到WHM面板&a…

暗区突围PC测试资格获取教程 人人可领100%获取方法

暗区突围PC测试资格获取教程 人人可领100%获取方法 暗区突围国际服的上线,近日在游戏圈内掀起了不小的浪花。而一个暗区突围国际服的测试资格更是成为了玩家们眼中炙手可热的宝物。许多玩家不知道该如何获取游戏的测试资格,今天小编就为大家带来详细的教…

电脑复制和粘贴的时候会出现Hello!

电脑不管是Microsoft Excel还是Microsoft Word复制之后粘贴过来就出现HELLO,当复制粘贴文件的时候就会出现WINFILE; 具体现象看下面两个图片: 这是因为winfile 文件病毒(幽灵蠕虫病毒),每月的28号发作; 症状…

【深度学习】YOLO源码中的mAP计算代码的理解笔记(大部分代码逐行+基础解释)

提示:本篇博客是在阅读了YOLO源码中的mAP计算方法的代码后加上官方解释以及自己的debug调试理解每一步是怎么操作的。由于是大部分代码进行了逐行解释,所以篇幅过长。 文章目录 前言一、输入格式处理1.1 转换公式二、init:初始化2.1 iouv2.2 …

2024版本idea集成SpringBoot + Ai 手写一个chatgpt 【推荐】

题目:SpringBoot OpenAi 在这里获取key和url:获取免费key base-url为这两个: 话不多说直接来! 一、简介 Spring AI 是 AI 工程的应用框架。其目标是将 Spring 生态系统设计原则(如可移植性和模块化设计&#xff…

【CAD建模号】学习笔记(四):工作平面

工作平面介绍 CAD建模号右侧导航栏提供了很多便捷的工具,有测量工具、坐标系、模型和图层切换、视图切换等。 1. 测量工具组 测量工具可以测量图形的几何体积,长度,角度等。工具组包含如下: 测量几何:可以测量图形的面…

C++多态实现原理详解

阅读引言: 我想象了一下, 假如人有突然问我什么是多态, 我该如何给别人说清楚呢?所以写下这篇文章, 希望大家看完有所收获。 ①. 开胃小菜 先看这样一个开胃小菜 这里我有点小小的疑惑, 大小为啥是1。 在C…

即插即用篇 | YOLOv8引入局部自注意力 HaloAttention | 为参数高效的视觉主干网络扩展局部自注意力

本改进已集成到 YOLOv8-Magic 框架。 我们提出了Axial Transformers,这是一个基于自注意力的自回归模型,用于图像和其他组织为高维张量的数据。现有的自回归模型要么因高维数据的计算资源需求过大而受到限制,要么为了减少资源需求而在分布表达性或实现的便捷性上做出妥协。相…

【知识碎片】2024_05_11

本篇记录了两个代码,【图片整理】是一个数组排序题,【寻找数组的中心下标】看起来很适合用双指针,但是细节多,最后还是没通过全部用例,看了题解写出来的。 C语言部分是两个知道错了之后恍然大悟的选择题。 每日代码 图…

1053: 输出利用先序遍历创建的二叉树中的指定结点的度

解法&#xff1a; c语言 #include<iostream> #include<vector> using namespace std; typedef struct tNodes{char val;tNodes* left, * right; }* tNode;void creat(tNode& t) {char ch;cin >> ch;if (ch #) t NULL;else {t new tNodes;t->val …

最少数量线段覆盖-华为OD

系列文章目录 文章目录 系列文章目录前言一、题目描述二、输入描述三、输出描述四、java代码五、测试用例 前言 本人最近再练习算法&#xff0c;所以会发布一些解题思路&#xff0c;希望大家多指教 一、题目描述 给定坐标轴上的一组线段&#xff0c;线段的起点和终点均为整数…

完整性验证器:迈向 Starknet 超高可扩展性的一大步

原文&#xff1a;https://www.starknet.io/en/content/the-integrity-verifier-a-leap-toward-starknet-hyperscaling&#xff1b;https://www.starknet.io/en/ecosystem/grant 编译&#xff1a;TinTinLand 核心观点 由 Herodotus 开发的完整性验证器&#xff0c;使开发者能够…

代码随想录算法训练营第六十三天| LeetCode84. 柱状图中最大的矩形

一、LeetCode 84. 柱状图中最大的矩形 题目链接/文章讲解/代码讲解&#xff1a;https://programmercarl.com/0084.%E6%9F%B1%E7%8A%B6%E5%9B%BE%E4%B8%AD%E6%9C%80%E5%A4%A7%E7%9A%84%E7%9F%A9%E5%BD%A2.html 状态&#xff1a;已解决 1.思路 这道题跟上道接雨水的题基本上是反…

【MySQL】锁

锁 全局锁 全局锁&#xff1a;对整个数据库实例加锁&#xff0c;加锁后整个实例就处于只读状态&#xff0c;其他语句都将被阻塞。 使用场景是&#xff1a;全库的逻辑备份 语法&#xff1a; 1、加全局锁 flush tables with read lock ;2、数据备份 mysqldump -uroot –pr…

【Web后端】web后端开发简介_Servlet简介

1.web后端开发简介 Java企业级开发&#xff0c;也就是学习]avaEE(Enterprise Edition)版本,是一种结构和一套标准。在应用中开发的标准就是Servlet、jsp和JavaBean技术。jsp技术现在已基本处于淘汰状态&#xff0c;简单了解即可web后端开发&#xff0c;基于B/S模式的开发体系。…

系分-历年论文题目

年份试题一试题二试题三试题四2023年信息系统数据转换与迁移敏捷开发方法论Devops及其应用论信息系统可行性分析2022年论原型法及其在信息系统开发中的应用论面向对象设计方法及其应用2021年论面向对象的信息系统分析方法论静态测试方法及其应用论富互联网应用的客户端开发技术…

13、FreeRTOS 事件标志组

文章目录 一、事件组(event group)的特性1.1 什么是事件标注组1.2 事件标注组的场景1.3 事件组的概念1.4 事件组的操作 二、事件组API2.1 创建2.2 删除2.3 设置事件2.4 等待事件2.5 同步点 一、事件组(event group)的特性 1.1 什么是事件标注组 事件标志位&#xff1a;表明某…

2024kali linux上安装java8

1 kali下载Java 8安装包 访问Oracle官网或其他可信的Java下载站点&#xff0c;如华为云的开源镜像站&#xff08;例如&#xff1a;https://repo.huaweicloud.com/java/jdk/8u202-b08/jdk-8u202-linux-x64.tar.gz&#xff09;。 确保下载的是与你的Kali Linux系统架构&#xf…