C++——vector(3)

2023-09-20 11:40:27

作者:几冬雪来

时间:2023年9月20日

内容:C++部分——vector内容讲解

目录

前言: 

erase: 

erase和insert总结:

resize:

深拷贝: 

赋值: 

结尾:


前言: 

在上一篇博客中我们更加介绍了vector的定位还特别的介绍了它的几个常用接口,也对接口的使用方法,注意事项,可能出错的地方以及接口的拓展都多多少少有些讲解,今天我们将继续对vector板块的知识进行补全。 

erase: 

在上一篇博客中我们讲解了insert,它的作用是在某个位置插入某个数据,也可以运用于头插和尾插

既然vector中有insert接口,那么肯定也存在作用与之相反的接口

erase接口,与insert相反,它的作用是删除某个位置的值。 

在理解完了insert之后,erase代码的意思我们也可以简单的看出来。

首先,删除的数据一定是要有效的,因此一开始要对其进行断言

接下来用it存放pos的下一个值。 

简单来说就是pos的下一个值覆盖原pos位置的值,然后it加加再次进行覆盖,最后it等于_finish的时候我们要将最后一个值删去。 

和insert会发生迭代失效一样,在某些特殊的情况下,erase也会发生迭代器失效的问题

与此同时我们的erase还有一个可能会出错的地方。

类似上边画的这种情况。

在这里我们想要删除5这个数据,一般来说删除数据的本质就是数据的覆盖,但是在5的后面并没有数据让我们进行覆盖的操作,这个时候就需要去移动_finish

但是代码中的it有进行++操作,这就会导致_finish和it错位开来,循环的条件永远都无法完成,且处于越界的状态

erase和insert总结:

在学习完了erase和insert之后,我们对其进行了一个大致的总结。

vector中,erase和insert迭代器对象后,不能再去访问那个迭代器。我们认为他失效,访问结果是未定义

resize:

在vector第一篇博客当中,我们讲解了resize和reserve的作用和区别,并且书写了它们的代码比较。

在今天我们将试一试在头文件中书写resize接口

这个地方我们放出可能会导致resize有3种不同书写格式的图。

在讲解resize的时候我们还有一种就是resize(x,y)的写法,这种写法就是开辟x的空间,每个位置的值都是y

接下来就在头文件处编写代码。 

这里就是resize的代码,然后要判断其大小,如果n小于size的话,这个地方就可以直接进行填值

如果大于,那么就先进行扩容操作最后再将其赋值,并且_finish也要进行移动,最后移动到_start+n的位置。 

但是在写resize代码的时候要注意一个点,就是在后一个想要传递的值不能直接写为int或者char类型

这是因为我们并不知道resize会被输入什么类型的值,可能是整形也可能是字符类型,因此这个地方需要我们传递一个缺省值让它自己判断

深拷贝: 

接下来就是讲解的是vector的一个重要的知识点。 

在vector中也存在着深浅拷贝的问题vector的书写中我们该运用的不是浅拷贝而是深拷贝。那么浅拷贝是什么样子的?

这就是浅拷贝的书写,两个v1和v都指向了同一块位置。因此析构的时候,它会被析构两次,这就导致代码的崩溃。     

在深拷贝中,还将其做了区分,一种是传统的深拷贝的书写,另外一种是偏今天的深拷贝的写法,这里我们就介绍一下传统的深拷贝的写法。 

在这里也是一样先创建出来_start等,将它们置空

接下来对其进行赋值,将v的_start,_finish等数据赋值给v1的_start,_finish,这就是我们传统的深拷贝

  

下面这一张图则是我们偏现代的书写方法,但是两种方法都是可以使用的,没有分谁优谁劣的说法。 

赋值: 

赋值是我们学习C语言和C++一定会认识的一个操作符,那么在vector使用赋值操作的时候要注意什么呢?

同样的,赋值操作在vector中也会涉及深浅拷贝的问题,也是两个定义指向了同一块位置

那么在头文件中,赋值操作又要怎么去写呢? 

头文件中也只是需要创建一个swap来讲v1的_start等值赋值给v2,最后返回*this即可完成vector中的赋值操作

其实到这里上面的浅拷贝都并不是什么大问题,接下来我们就来讲解vector中会因为浅拷贝而出现的问题。 

在这里我们可看见最后结果处显示代码为-10737···,这就表示代码出现了错误

这个地方隐藏着一个深拷贝的问题

在这个地方也是在扩容的时候出现了问题(4个的时候为正常结果),那么是什么问题。 

 

因为我们的代码是vector中包含着string,因此和整形类型等不同在这里面存储的是自定义类型。 

最主要的问题就是在扩容时候的memcpy和delete。 

在reserve的时候,创造新空间和异地扩容都没问题。但是memcpy能有效的解决内置类型,却不能够解决自定义类型。 

再在下一步进行delete的时候,delete会释放那一段数据的空间。但是相比较free,delete删除数据会多做几步,delete[]它会指向的数组空间先调用析构函数,也就是调用string的析构函数。 

它就会将我们的数据进行析构,再把空间释放掉。 

因此如果T是自定义类型的时候,delete会依次调用数组每个对象析构函数,在释放整个空间。 

可以说这里是vector进行深拷贝,但是string还是浅拷贝的状态。 

那么要怎么去改写代码呢? 

在这个地方要进行修改,我们使用了一种常见的方式,它是将原先空间的值赋值到我们新空间当中

这样子后边delete之后就不会将数据析构掉。 

同样的在拷贝构造的地方我们也有使用到memcpy,这里也要对其进行修改。 

在这里我们对这个问题的解决方法是。

如果T是string这样的深拷贝的类,调用的是string赋值重载,实现的string对象的深拷贝。 

结尾:

到这里我们的vector板块的知识就告一段落了,在下一篇博客中我们将讲解C++的另外的知识,最后希望这篇博客能够带来一些帮助。 

更多推荐

【PX4】PX4第一个offborad例程

【PX4】PX4第一个offborad例程文章目录【PX4】PX4第一个offborad例程1.什么是OFFBOARD2.第一个offboard例程3.编写launch文件Reference1.什么是OFFBOARDPX4的OFFBOARD指的是外部控制模式,飞行器根据飞行控制栈外部(如机载计算机)提供的设定值控制位置

API安全

1API的简介API代表应用程序编程接口,它由一组允许软件组件进行通信的定义和协议组成。作为软件系统之间的中介,API使软件应用程序或服务能够共享数据和功能。但是API不仅仅提供连接基础,它还管理软件应用程序如何被允许进行通信和交互。API控制程序之间交换请求的类型、请求的方式以及允许的数据格式。例如,智能手机上的天气

小谈设计模式(2)—简单工厂模式

小谈设计模式(2)—简单工厂模式专栏介绍专栏地址专栏介绍简单工厂模式简单工厂模式组成抽象产品(AbstractProduct)具体产品(ConcreteProduct)简单工厂(SimpleFactory)三者关系核心思想Java代码实现首先,我们定义一个抽象产品接口Product,其中包含一个抽象方法use():然后

Redis的缓存、消息队列、计数器应用

目录一、redis的应用场景二、redis如何用于缓存三、redis如何用于消息队列四、redis如何用于计数器一、redis的应用场景Redis在实际应用中有广泛的应用场景,以下是一些常见的Redis应用场景:缓存:Redis可以用作缓存层,将频繁读取的数据存储在内存中,提高数据读取速度,减轻数据库负载。计数器:Re

Vulnhub系列靶机---HarryPotter-Fawkes-哈利波特系列靶机-3

文章目录信息收集主机发现端口扫描dirsearch扫描gobuster扫描漏洞利用缓冲区溢出edb-debugger工具msf-pattern工具docker容器内提权tcpdump流量分析容器外-sudo漏洞提权靶机文档:HarryPotter:Fawkes下载地址:Download(Mirror)难易程度:难上难信

Redis 集合操作实战(全)

目录SADD插入集合SCARD取元素数量SPOP随机移除元素SREM移除多个元素SMOVE移动元素到别的集合SMEMBERS取所有成员SRANDMEMBER取指定数量元素SISMEMBER判断元素是否存在SUNION多集合求并集SUNIONSTORE多集合求并集(存储)SINTER多集合求交集SINTERSTORE多集

PY32F003F18之比较器问题

PY32F003F18的模拟模块,其内部参考电压容易受到电源电压影响。当我连接"USB转串口的RXD"时,PC接收到模拟数据均正常;当我连接“USB转串口的TXD”时,发现内部参考电压的AD值为0xFFF。断开连接的“USB转串口的TXD”,模拟功能模块又恢复正常。于是用万用表测量“USB转串口的TXD”的电压,开路电

Spring高手之路10——解锁Spring组件扫描的新视角

文章目录1.组件扫描路径2.按注解过滤组件(包含)3.按注解过滤组件(排除)4.通过正则表达式过滤组件5.Assignable类型过滤组件6.自定义组件过滤器7.组件扫描的其他特性7.1组合使用组件扫描8.组件扫描的组件名称生成8.1Spring是如何生成默认bean名称的(源码分析)8.2生成默认bean名称的特殊情

一文巩固Spring MVC的Bean加载机制

目录一、什么是SpringMVC的Bean二、SpringMVC的Bean加载机制三、SpringMVC如何动态装载Bean一、什么是SpringMVC的Bean在SpringMVC中,Bean指的是在SpringIoC容器中创建和管理的对象。这些对象可以是普通的Java类,也可以是服务层组件、数据访问对象(DAO)或

手动实现 Spring 底层机制【初始化 IOC容器+依赖注入+BeanPostProcessor 机制+AOP】之实现任务阶段 5- bean 后置处理器

😀前言手动实现Spring底层机制【初始化IOC容器+依赖注入+BeanPostProcessor机制+AOP】的第五篇具体实现了任务阶段5-bean后置处理器🏠个人主页:尘觉主页🧑个人简介:大家好,我是尘觉,希望我的文章可以帮助到大家,您的满意是我的动力😉😉在csdn获奖荣誉:🏆csdn城市之星2名⁣⁣⁣

kafka rabbitmq 详细对比

Kafka&rabbitmqkafkaProducer:消息生产者,将消息push到Kafka集群中的Broker。Consumer:消息消费者,从Kafka集群中pull消息,消费消息。ConsumerGroup:组团消费,每个Consumer都属于一个ConsumerGroup。消费者组在逻辑上是同一个订阅者。消费

热文推荐