【C++初阶】STL——Vector从入门到应用完全指南(1)

🎈主页传送门:良木生香

🔥个人专栏:《C语言》 《数据结构-初阶》 《程序设计》《鼠鼠的C++学习之路》 《Linux系统编程》

🌟人为善,福随未至,祸已远行;人为恶,祸虽未至,福已远离



前言:在之前的学习中,我们已经将C++STL容器部分的String类进行了学习,知道了STL容器的基本用法以及常见接口。那么今天我们就来继续学习STL中容器中的Vector,看看它有哪些点是和string相似和不同点


一、基本接口的使用

1.1、定义:

从定义中我们可以看到,Vector与String相似,也是一个模板,毕竟是为了支持多种数据的插入

1.2、构造 && 析构

构造:

虽然Vector有多种构造方式,但是在日常使用中使用更多的还是默认构造和拷贝构造。

析构:

对于析构函数,如果不是自己写的话,就不用去关心这么多,因为在日常使用中Vector自带的析构函数已经非常完美了,但如果是自己写的构造函数,那就要自己手动写析构了。

1.3、流插入和流提取

Vector是不支持流插入和流提取的,即不能用cin和cout对其进行输入和输出。当我们想要对数据进行输入和输出时,可以用上我们的三种遍历方式:下标+[ ]范围for 以及迭代器iterator

下面就进行小小的演示:

运行结果为:

在C++11中新增加了一个小特性:initializer_list,也就是允许用{元素}方式直接给vector进行初始化。还有一点就是:有迭代器就能使用范围for,这就是为什么string类和vector都能使用范围for的原因。

1.4、size && max_size && capacity

讲到容器,就不得不提它的容量大小了。

size()依旧计算的是元素的个数,max_size是计算当前环境下能存放的最大数量的元素个数,capacity()值得则是当前穷奇的容量,我们以v2为例子,看看数据是怎么样的:

这里我们也能看一下windows和Linux在vector上的capacity扩容方式:

vs中的扩容方式是这样的:

大概呈1.5倍的扩容方式,而Linux下的环境则是这样的:

同样的代码,在Linux环境下则是标准的二倍扩容。

1.5、reserve

既然都讲到了空间扩容,我们就来看看reserve能为我们的程序提升多大的效率:

假设我们差如十亿个数据,下面是使用reserve的情况:

耗时在两秒左右,那不使用reserve有是多久呢?

用了三秒左右,可见使用reserve之后程序运行的效率能大大提高啊。

既然扯到了reserve,那我们再来将他和resize对比一下:

从定义中我们能看到,resize具有开空间的同时又能对空间进行初始化,但是reserve只能开空间,并不会赋值。

1.6、对元素的操作:

1.6.1、push_back && pop_back

这两个接口顾名思义就是尾插尾删 ,两者的定义如下:

他们的具体使用方法如下:

既然有了尾删和尾插,那有没有头删和头插呢?有的:

1.6.2、insert && erase

两者的定义如下:

其实他们实现的是在某个位置进行插入和删除,但是我们只用将位置设定在头部就能实现头删和头插了:

在实现的时候要注意,在调用一次insert或者erase之后都要将it(iterator)的指向进行修改,因为这两个操作可能会修改容器的起始指针。

1.6.3、swap && clear

这两者在平时中使用的场景并不是很多,但是还是要注意一下,先看定义:

1.swap交换的其实并不是两个容器之间的数据,而是指向两个容器的指针,即容器A的指针指向容器B,容器B的指针指向容器A。

2.clear在被调用时只是清除数据,并不会起到释放空间的作用。

1.6.4、emplace_back && emplace

两者的定义如下:

这两者的区别就相当于inset和push_back的区别,但是emplace_back和push_back亦有差距,当vector中存放当元素是了结构体或者是类类型时,传进去的多个参数会触发多参数的隐式类型转换,即将多个参数自动构造成一个类类型对象或者是结构体对象并存入vector中。

但是:

1.push_back()在对多参数类型进行隐式类型转换的时候,会先用多参数创建一个临时对象,在对临时对象进行拷贝,最后才放进vecotr中。

2.emplace_back()则是直接在vector中直接用参数构造类类型对象或者是结构体对象。

综上,emplace_back()的效率会比push_back()要高一些。

既然emplace_back()的效率要比push_back()要高,那为什么还要保留push_back()?

就是因为当已经有现成对象的时候,使用push_back()的效率又会更高效,而emplace_back()则是将对象的参数拆分出来,这样就得不偿失了,所以两者在不同场景下都各有优点。

总结:

emplace_back():没有现成对象,只传参数的时候,效率更高;并且能传构造对象的参数,也能传对象(emplace_back(aa1)->对象 / emplace_back(1,2)->参数)

push_back():只能传对象(现有对象/临时对象),如果传参数也是先构造成临时对象,再将临时对象进行拷贝再传入vector,所以本实质上还是只能传对象。(push_back({1,2})->参数->临时对象(多参数的隐式类型转换))

二、简单练习

讲完了基本接口的使用,现在来做两道题练练手:

2.1、只出现一次的数字:

136. 只出现一次的数字 - 力扣(LeetCode)https://leetcode.cn/problems/single-number/description/

题解很简单,使用异或对所有数字进行遍历即可,因为只有一个数字出现一次,那么其他数字就只可能多次重复出现或者都不出现,在异或运算之后,重复出现的数字会被异或成0,而0和任何数字异或还是那个数字(当然前提是每个数字出现的次数都是偶数次,如果是基数次的话那就要用到分组异或了)

2.2、杨辉三角

118. 杨辉三角 - 力扣(LeetCode)https://leetcode.cn/problems/pascals-triangle/description/

这道题是挺有意思的,我么你可以将其分为C语言版的和C++版本的C++版本呢

先来看看C++版本的:

可以看到,你这个函数的接口非常的简单,只用我们返回一个二维vector的指针,那么我们先通过画图来理解一下这个二维的vector:

可以看到,二维的vector就是由一个一个vector拼接起来组成的,那么想要实现杨辉三角,我们就要先开numRows长的空间来存放vector<int>类型的数据,再对每个vector<int>放入int 类型的数据,那么具体的代码如下:

整个过程非常的简单,后面就是对杨辉三角进行一些元素的处理了。

现在我们再来看看C++版本的:

这里要传入的参数就比C++版本的多得多了,由图可见上面有一堆绿色的注释,简单来说就是:

returnSize是这个二维数组有几行,returnColumnSize是这个数组有几列,并且返回时的数组必须都是要由自己开空间得来的。

*returnColumnSize是一个指针数组的地址,而returnSize是int类型数组的地址想要实现二维数组,那就要先创建一个指针数组,存放每一个整型数组的指针,在对每一个整型数组的书v就进行处理,就得到了杨辉三角的C语言版本。

代码入下:


那么以上就是本次所有的内容了

文章是自己写的哈,有什么描述不对的、不恰当的地方,恳请大佬指正,看到后会第一时间修改,感谢您的阅读~~~~


博主笔记:

相关推荐
Brilliantwxx1 小时前
【C++】String的模拟实现(代码实现与坑点讲解)
开发语言·c++·笔记·算法
憨波个1 小时前
【说话人日志】DOVER:diarization 输出融合算法
人工智能·算法·音频·语音识别·聚类
skilllite作者1 小时前
Zed 1.0 编辑器深度评测与实战指南
开发语言·人工智能·windows·python·编辑器·agi
babe小鑫1 小时前
数据岗位的发展与学习数据分析指南
学习·数据挖掘·数据分析
爱学习的张大1 小时前
具身智能论文问答(四):pi0
人工智能·算法
楼田莉子1 小时前
仿Muduo的高并发服务器:Channel模块与Poller模块
linux·服务器·c++·学习·设计模式
zhouwy1131 小时前
Linux网络编程从入门到精通
linux·c++
迷途之人不知返1 小时前
deque的简单认识
数据结构·c++
上弦月-编程1 小时前
指针编程:高效内存管理核心
java·数据结构·算法