c++:vector

server/2025/3/2 2:59:09/

1.使用

1.1构造函数

常见的三种构造方式:空构造,拷贝构造,指定元素构造

1.2iterator

begin和end也分为正向和反向。

注意:反向迭代器可以反向遍历是因为在定义rbegin和rend函数的时候把尾地址给到了rbegin,而不是说改个reverse_iterator就可以这么简单

1.3空间

(1)resize:可以用于确定元素个数的初始化,以及插入n个相同元素

(2)reserve:可以扩充数组容量

这是扩容前,我们看到它的空间容量是15

这扩容后,它的空间容量是30

1.4获取首尾数据

front:获取首数据,back获取尾元素

因为front取得是首元素,所以我们这里把首元素改成2,back取得是尾元素,所以这里我们把尾元素改成3

2.动态二维数组理解

静态的二维数组其实是先把划给数组的空间分为几大块,有几行就分几块,然后在每块里面再细分出来给具体的元素存储。

而动态的二维数组是先弄一个数组存每行的地址,这个地址是动态开辟的数组的地址,这个动态开辟的数组存的才是数据

3.迭代器的分类

1.单向迭代器:支持迭代器++

eg:单链表,哈希表

2.双向迭代器:支持++,--

eg:list,set,map

3.随机迭代器:支持++,--,=,-

eg:vector,string

4.底层部分实现

4.1基础结构搭建

(1)因为我们需要利用迭代器实现vector和算法的链接,所以先把迭代器typedef出来,对于数组结构,对应数据的指针就可以实现迭代器的功能

(2)之前的数组我们都是使用索引去访问数据,这里也是为了和算法接上,所以改成迭代器的形式,m_start表示首元素的迭代器位置,m_finish表示尾元素的下一个位置的迭代器位置。m_end_of_storage表示空间边界的下一个位置

4.2迭代器构建

首先是需要typedef出iterator,因为对于数组这个数据结构指针就可以充当迭代器实现访问。

然后我们把begin()和end()的值给上

4.3reserve实现 

因为我们不实现缩容,所以这里我们需要知道capacity是多少,且后面的实现还需要知道有效数据个数,所以我们先把这两个功能实现一下

1.capacity

2.size

接下来实现reserve

首先判断是否满足指定的容量值大于当前容量值,若大于则开始进行扩容。

扩容:

1.根据val创建新的空间

2.拷贝对应值

3.释放旧空间

4.更新数组内置三个迭代器的值

但是这里会有个大问题:m_finish的指向会有问题

因为此时调用size,用的是旧的m_finish和新的m_start相减,m_start已经是指向新开辟的空间的迭代器,与m_finish八竿子打不着。我们有两种解决方式

方法一:换顺序

调换赋值顺序,我们把m_finish的赋值和m_start的赋值顺序换一下,这样就可以用旧的m_start和旧的m_finish相减,从而得到正确的size大小

方法二:变量存值

在扩容前,先用一个oldsize存储旧的size,后面赋值就不再调用size,而是直接使用oldsize。

方法二要比方法一更好,因为你无法保证其他程序员会不会去动你的代码顺序。

方法二实现


补充:由于实现模板需要考虑到各种数据类型,所以我们的reserve其实不能使用memcpy来实现数据拷贝,因为他是一个一个字节去拷贝的,实现的是浅拷贝。

对于需要深拷贝的我们应该实现深拷贝

这里对于内置类型则与之前没区别,但是对于自定义类型就可以调用赋值重载来实现深拷贝了

4.4尾插与尾删

 尾插前判断容量是否足够,如果不足就reserve,不过也要考虑到capacity为0的情况,若为0就给四个字节空间,否则就按照原本空间两倍来开

插入数据就直接解引用给值即可。


4.5 任意位置插入

第一步:容量判断与扩容

第二步:挪动数据

第三步:插入数据并更新迭代器


注意:insert在需要扩容的情况下会出现pos迭代器失效的问题!!!

因为扩容后m_start和m_finish变位置了,而pos还是旧的位置,所以while循环会出问题。

我们应该在扩容完成前把旧的pos和start之间的距离保存下来,然后更新pos位置,用新的pos进行while判断

还有一个要注意的是,我们既然利用了迭代器去访问数据,就用上解引用符号来访问


一旦我们使用了insert或erase这些用了迭代器的方法之后,默认这个传入的迭代器就失效了,不能接着使用

4.6删除

 

第一步:挪动数据,从pos的下一个位置开始挪动,直到最后一个位置的元素也挪动完为止

第二步:更新迭代器

4.7resize实现

 

总共分两种情况:删除和插入

删除:需要的size大小比原来的size还小,所以删除,把m_finish更新一下即可

插入:需要的size大小比原来的size还大,所以插入,无论是否需要扩容,我们先reserve,对于需要扩容的reserve会自动扩,不用的则不会有任何操作。然后进行插入,直到到达目标size

4.8构造函数

(1)普通构造 注意:如果我们写了任意一个构造函数,系统就不会再给我们自动实现默认构造了

 (2)拷贝构造

我们对于含有指针等类型的自定义类型需要实现深拷贝,而这里我们实现的是vector的模板,所以要考虑到这一点。

直接遍历然后尾插即可,不过因为尾插会涉及很多次扩容,效率较低,所以我们先提前用reserve开好空间


(3)数值直接传递的构造

在说这个构造之前我们先了解一下initializer_list这个类。

他和数组的使用很类似,不过他的类只支持begin,end和size三个方法。

和拷贝构造的实现方法类似,不再重复说明

使用:

这样我们就可以实现传递多个值的构造函数


(4)迭代器区间初始化

由于我们利用迭代器区间初始化的时候不仅仅是使用自己这个类的迭代器,而是适用于所有类型的迭代器,所以这里我们创建一个迭代器模板,以此兼容所有迭代器。


(5)n个数值构造

疑问:为什么我们要实现两个方法?

因为第一个方法在一种常见的情况下会出问题,导致匹配的构造方法是迭代器区间的构造方法。

这里我们的两个数据都是int型,而如果只实现第一个方法,在匹配度上就不如迭代器区间构造的匹配度,所以会调用迭代器区间初始化,造成非法间接寻址

所以我们多重载一个构造函数就可以解决这个问题

4.9赋值重载

 

我们实现的是赋值重载的现代写法,在传参的时候就已经利用拷贝构造构建出了一个和赋值的数组内容一样的数组,我们直接把被赋值数组和新创建的数组的内容换掉就可以实现赋值功能了。

在这里我们用到了swap

由于vector中就只包含三个变量,所以我们把这三个迭代器都交换就行了

文章来源:https://blog.csdn.net/2301_79954395/article/details/144970235
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ppmy.cn/server/163855.html

相关文章

计算机毕业设计Python+知识图谱大模型AI医疗问答系统 健康膳食推荐系统 食谱推荐系统 医疗大数据 机器学习 深度学习 人工智能 爬虫 大数据毕业设计

温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…

【Elasticsearch】中数据流需要配置索引模板吗?

是的,数据流需要配置索引模板。在Elasticsearch中,数据流(Data Streams)是一种用于处理时间序列数据的高级结构,它背后由多个隐藏的索引组成,这些索引被称为后备索引(Backing Indices&#xff0…

开源PDF分割合并工具 PDFsam Basic v5.3.0绿色版

PDFsam Basic是一款 免费开源的PDF分割合并工具 它旨在 拆分、合并、提取页面、混合和旋转 PDF文件 PDF合并 合并是最常用的PDFsam Basic功能,它让您将PDF文件结合在一起 页面范围 输入的PDF文件可以完整或部分地合并。页面选择可以以逗号分隔的页面间隔&#xf…

leetcode_链表 21.合并两个有序链表

21.合并两个有序链表 将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。思路: 定义一个哑节点(dummy node),哑节点是一个初始的虚拟节点,它不存储有效值,只…

【计算机网络】设备更换地区后无法访问云服务器问题

文章目录 1. **服务器的公网 IP 是否变了**2. **服务器的防火墙或安全组设置**3. **本地运营商或 NAT 限制**4. **ISP 限制或端口封锁**5. **服务器监听地址检查** 1. 服务器的公网 IP 是否变了 在服务器上运行以下命令,检查当前的公网 IP:curl ifconfi…

【游戏设计原理】93 - 节奏

与“序-破-急”类似的节奏概念广泛存在于全球不同文化和创意领域中。以下是一些常见的节奏框架和理论,它们与“序-破-急”在本质上有相似之处,但体现出不同的风格和应用: 1. 三幕式结构(Three-Act Structure) 来源&a…

179最大数(贪心算法)分析+源码+证明

文章目录 题目题目分析算法原理 源码证明 思考 题目 给定一组非负整数 nums,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数。 注意:输出结果可能非常大,所以你需要返回一个字符串而不是整数。 题目分…

探索JavaScript前端开发:开启交互之门的神奇钥匙(二)

目录 引言 四、事件处理 4.1 事件类型 4.2 事件监听器 五、实战案例:打造简易待办事项列表 5.1 HTML 结构搭建 5.2 JavaScript 功能实现 六、进阶拓展:异步编程与 Ajax 6.1 异步编程概念 6.2 Ajax 原理与使用 七、前沿框架:Vue.js …