C++ stl容器vector的认识与简单使用

目录

前言:

 本篇文档图片引用自:https://cplusplus.com/reference/vector/vector/

1.vector的结构

2.迭代器类型

3.构造函数

4.迭代器

反向迭代器遍历

const迭代器

5.容量

maxsize

shrink_to_fit

reverse

resize

6.修改

insert和erase

7.vector的3种常见遍历

总结:


前言:

本篇来认识与简单使用一下容器vector,vector算是使用比较频繁的容器了,这里只介绍常用的接口。还会介绍一下像迭代器的类型的一些内容,方便为下面实现与其它容器打基础。

 本篇文档图片引用自:https://cplusplus.com/reference/vector/vector/

1.vector的结构

vector是通过动态的顺序表,动态也就是所谓的可以扩容,而顺序表也不陌生,就是数组。

vector支持对任意类型的储存,当然vector<vector<int>>这样的也不见怪。

另外vector中的第二个模版参数为一个空间配置器, 是为了申请空间时不必一直像系统申请内存,所以还有一个内存池的概念,这里暂时不再展开。

2.迭代器类型

迭代器分为三种类型:单向迭代器,双向迭代器,随机迭代器。

forward_list单链表,unordered map类型的迭代器就是单向迭代器,只能++,不能--,所以也就没有rbegin这样的反向迭代器。

list类型的迭代器就是双向迭代器,可以++,--,但不能+,-。

vector和string类型的迭代器就是随机迭代器了,可以++,--,+,-。这一点在下面会展示。

int main()
{
	vector<int> v1;
	vector<int> v2(v1.begin()+5, v1.end()--);//随机迭代器,使用正确

	forward_list<int> f1;
	forward_list<int> f2(f1.begin(),f1.end()--);//单向迭代器,报错
	forward_list<int> f3(f1.begin()+2,f1.end());//单向迭代器,报错

	list<int> l1;
	list<int> l2(l1.begin(),l1.end()--);//双向迭代器,使用正确
	list<int> l3(l1.begin()+2,l1.end());//双向迭代器,报错


	return 0;
}

3.构造函数

(1)是无参的构造,而里面的参数是代表可以构造的时候自己传一个自己写的空间配置器,暂时不用管,默认为无参的。

(2)是带参的构造,先传一个要初始化的个数,再传初始化的值。 

	vector<int> v2(10, 1);
	for (auto e : v2)
	{
		cout << e << endl;
    } 

(3)是传迭代器区间,因为它是一个模版所以现在传什么类型的迭代器都可以。而这里的InputIterator,查阅参数类型的解释,它是一个:

这里的input iterator的迭代器类型就支持我们刚刚说的三种迭代器类型,分别是单向,双向,与随机迭代器。所以说,当我们往参数传迭代器类型的时候,就会判断这个迭代器的类型,进而限制使用一些操作。

	vector<int> v2(10, 1);
	for (auto e : v2)
	{
		cout << e << endl;
	}
	vector<int> v3(v2.begin(), v2.end());
	for (auto e : v3)
	{
		cout << e << endl;
	}

 注意,所有的迭代器区间的范围都是左开右闭。

	string s1("hello world");
	vector<char> v4(s1.begin(), s1.end());
	for (auto e : v4)
	{
		cout << e << endl;
	}

string迭代器区间进行构造 vector对象。

(4)是拷贝构造。

4.迭代器

迭代器上面已经介绍的差不多了,迭代器是容器通用的,它是主力军,因为对于string和vector遍历使用内部重载的[]比较方便,但到了后面使用list再使用[]便利时间复杂度就高了。(因为链表的排列不是顺序的,找到对应的元素就需要遍历一遍,而使用迭代器就不会有这样的烦恼了。)

反向迭代器遍历:
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);

	//vector<int>::reverse_iterator rit = v1.begin(); //报错
	//auto rit = v1.rbegin();                         //可以这样写,但是可读性不高

	vector<int>::reverse_iterator rit = v1.rbegin();
	while (rit != v1.rend())
	{
		cout << *rit << " ";
		++rit;
	}
	cout << endl;

注意不使用配套的迭代器会报错,例如使用迭代器接收反向迭代器,类型不匹配。

迭代器类型可以使用auto来根据后面的内容进行推导,但是可读性不高。 

const迭代器:

只读不能写,可以使用begin(),也可以使用c++11的cbegin()。

5.容量

maxsize:
最大40多亿字节。也有可能是10多亿对象就是除以整型的4字节,相当于有10多亿的对象,用的不多,不同平台实现不一样,现实意义不大。

shrink_to_fit:

少用,就算原本有capacity为100,resize(10)也不会缩容,只会改变size,用shrink_to_fit会缩,但是大部分都不是原地缩容(开空间的函数例如malloc都没有说原地缩容的)。异地缩容代价很大,需要开一块空间,再进行拷贝。

reverse:

空间容量不够,自动扩容,不同的编译器自动扩容的大小不一样。

打印日志观察自动扩容:

可以看到vs下大概是1.5倍扩容的,而linux下是大概2倍扩容的。

reverse的作用就是:一方面如果提前知道有多大的空间使用,使用reverse提前开好空间,就不会让编译器自动扩容而可能造成空间的浪费;另一方面reverse提前一步扩好容,开好空间,肯定比编译器自动的满了扩一次,满了再扩一次的效率上有一定的提升。

resize:
就是开空间加初始化。

6.修改

insert和erase:

由于vector没有查找的接口,所以推荐使用库中的查找函数find,同样也可以供所有容器使用:

 注意模版中的first和last参数,文档中有详细的解释,如果找到了,就返回第一个与查找值相同的位置的迭代器;如果没有找到,就返回迭代器的右开区间:

	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);


	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

	vector<int>::iterator pos = find(v1.begin(), v1.end(), 1);
	if (pos != v1.end())
	{
		v1.insert(pos, 20);
	}
	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

上面代码中查找到的1也就是pos的位置可以理解为位于下标0的位置,所以返回的迭代器是指向第一个位置的, 所以再在pos这个迭代器位置插入数据就是在第一个位置插入数据也就是在开始插入一个20:

对于erase而言,不能直接就删除,还需要再查找一遍,不然会面临迭代器失效的问题,这里在后面的底层实现中会详细分析:

正确做法: 

	pos = find(v1.begin(), v1.end(), 2);
	if (pos != v1.end())
	{
		v1.erase(pos);
	}
	for (auto e : v1) {
		cout << e << " ";
	}
	cout << endl;

但是对于头尾的数据是可以直接删除的,至于为什么,后面再说:

	v1.erase(v1.begin());
	v1.erase(v1.end() - 1);
	for (auto e : v1) {
		cout << e << " ";
	}
	cout << endl;

7.vector的3种常见遍历

	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);

	for (size_t i = 0; i < v1.size(); ++i)
	{
		cout << v1[i]<< " ";
	}
	cout << endl;

	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

	vector<int>::iterator it = v1.begin();
	while (it != v1.end())
	{
		cout << *it++<< " ";
		//++it;
	}
	cout << endl;

 注意范围for的缺点就是不能倒着遍历。

总结:

本篇主要需要掌握vector的基本使用例如使用迭代器遍历,下标遍历,范围for遍历,还要掌握迭代器的类型,重要的是迭代器的插入与修改,引出的迭代器失效问题会在vector的底层模拟实现中涉及。

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

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

相关文章

心跳机制原理学习

心跳机制 应用场景&#xff1a; 在长连接下&#xff0c;有可能很长一段时间都没有数据往来。理论上说&#xff0c;这个连接是一直保持连接的&#xff0c;但是实际情况中&#xff0c;如果中间节点出现什么故障是难以知道的。更要命的是&#xff0c;有的节点&#xff08;防火墙…

4月6号排序算法(2)

堆排序 讲堆排序之前我们需要了解几个定义 什么叫做最大堆&#xff0c;父亲节点&#xff0c;以及孩子节点 将根节点最大的堆叫做最大堆或大根堆&#xff0c;根节点最小的堆叫做最小堆或小根堆。 每个节点都是它的子树的根节点的父亲 。 反过来每个节点都是它父亲的孩子 。 …

Matplotlib实现数据可视化

Matplotlib是Python中应用较为广泛的绘图工具之一&#xff0c;首次发布于2007年。它在函数设计上参考了MATLAB&#xff0c;因此名字以"Mat"开头&#xff0c;中间的"plot"代表绘图功能&#xff0c;结尾的"lib"表示它是一个集合。Matplotlib支持众…

HarmonyOS实战开发-短时任务

介绍 本示例主要展示后台任务中的短时任务。 通过ohos.resourceschedule.backgroundTaskManager &#xff0c;ohos.app.ability.quickFixManager 等接口实现应用热更新的方式去展现短时任务机制。 效果预览 使用说明 1.安装本应用之前&#xff0c;先编译好未签名的应用包&a…

【MPI并行程序】完美解决Attempting to use an MPI routine before initializing MPI

文章目录 错误原因解决方案 最近在写并行程序&#xff0c;犯了一个小错误&#xff0c;记录一下&#xff0c;以防止以后再犯。 Attempting to use an MPI routine before initializing MPI&#xff08;在初始化 MPI 之前尝试使用 MPI 例程&#xff09; 错误原因 这个错误通常是因…

MySQL学习笔记2——基础操作

基础操作 一、增删改查1、添加数据2、删除数据3、修改数据4、查询语句 二、主键三、外键和连接1、外键2、连接 一、增删改查 1、添加数据 INSERT INTO 表名[(字段名[,字段名]…)] VALUES (值的列表); --[]表示里面的内容可选添加数据分为插入数据记录和插入查询结果 插入数据…

【Vuforia+Unity】AR判断当前平台获取点击/触摸坐标点选中识别的二维码跳转网页

实现了&#xff1a;【VuforiaUnity】判断当前平台获取点击/触摸坐标点选中识别的二维码跳转网页 using UnityEngine; using Vuforia; public class BarcodeScanner : MonoBehaviour { public TMPro.TextMeshProUGUI barcodeAsText; string platformNum""; privat…

Java研学-RBAC权限控制(一)

一 权限控制 1 介绍 RBAC&#xff08;Role-Based Access Control&#xff0c;基于角色的访问控制&#xff09;是一种流行的权限控制策略&#xff0c;用于实现复杂系统的安全访问管理。它通过将权限与角色相关联&#xff0c;而不是直接与用户相关联&#xff0c;从而简化了权限管…

《QT实用小工具·二十三》 Ntp校时类

1、概述 源码放在文章末尾 该项目实现了 Ntp校时类 &#xff0c;包含如下功能&#xff1a; 可设置Ntp服务器IP地址。 推荐用默认的阿里云时间服务器 ntp1.aliyun.com 收到时间信号发出。 时间精确到秒。 下面是demo演示&#xff1a; 项目部分代码如下&#xff1a; #if…

组态王与美国罗克韦尔AB PLC之间无线通讯方案详解

组态王与多台美国罗克韦尔AB PLC间的无线通信测试需要用到以下设备&#xff1a; 三菱PLC型号&#xff1a;FX5u 2台 上位机&#xff1a;组态王6.55 1台 达泰欧美系PLC无线通讯终端——DTD418MB 3块 主从关系&#xff1a;1主2从 通讯接口&#xff1a;RJ45接口 供电&…

传统前端 JS 开发者有福了

大家好&#xff0c;春天的百花绽放之际&#xff0c;各个行业也迎来了各自的新生与挑战。有的继续沉下心来夯实基础&#xff0c;有的大力发展出海业务&#xff0c;又或者通过顶级促销套路天女散花般地贩卖高仿保时捷……这厢 Mendix 各位技术小伙伴继续紧跟时代脉搏&#xff0c;…

【linux】拓展知识-linux图形界面(GUI 程序)、X11介绍

linux图形界面 Linux 本身是没有图形化界面的&#xff0c;linux只是一个基于命令行的操作系统&#xff0c;所谓的图形化界面系统只不过中 Linux 下的应用程序。没有图形界面linux还是linux&#xff0c;很多装linux的WEB服务器就根本不装X服务器。 这一点和 Windows 不一样。W…

制作一个RISC-V的操作系统十-Trap和Exception(流 mtvec mepc mcause mtval mstatus trap完整流程)

文章目录 流mtvecmepcmcausemtvalmstatustrap 初始化trap的top half&#xff08;硬件完成&#xff09;trap的bottom half&#xff08;软件完成&#xff09;从trap返回代码实现 流 控制流&#xff1a;程序控制的执行流 trap分为中断和异常 mtvec base&#xff1a;存储trap入…

python|sort_values()排序

sort_value()可以用来对值&#xff08;比如说年龄&#xff09;进行排序 根据 ‘Age’ 列进行升序排序&#xff0c;如果 ‘Age’ 相同则根据 ‘Name’ 列进行降序排序 df_sorted_multi df.sort_values(by[Age, Name], ascending[True, False]) print(df_sorted_multi)

如何在WHM面板上更改主机名

本周有一个客户&#xff0c;购买Hostease的独立服务器并选择了WHM控制面板&#xff0c;询问我们的在线客服&#xff0c;如何在WHM面板上更改主机名。我们为用户提供教程&#xff0c;用户很快完成了设置。在此&#xff0c;我们分享这个操作教程&#xff0c;希望可以对您有帮助。…

SpringBoot内容协商快速入门Demo

1.什么内容协商 简单说就是服务提供方根据客户端所支持的格式来返回对应的报文&#xff0c;在 Spring 中&#xff0c;REST API 基本上都是以 json 格式进行返回&#xff0c;而如果需要一个接口即支持 json&#xff0c;又支持其他格式&#xff0c;开发和维护多套代码显然是不合理…

超图SuperMap-Cesium,地形图层,可以渲染一个或多个地形(地形可缓存DEM,TIN方式),webGL代码开发(2024-04-08)

1、缓存文件类型TIN格式&#xff0c;TIN的地形sct只能加一个 const viewer new Cesium.Viewer(cesiumContainer); viewer.terrainProvider new Cesium.CesiumTerrainProvider({isSct: true, // 是否为iServer发布的TIN地形服务,stk地形设置为falserequestWaterMask : true,…

代理IP在爬虫中的连接复用与开销减少

目录 一、引言 二、代理IP的基本概念 三、代理IP在爬虫中的使用 四、代理IP的连接复用 五、减少开销的策略 六、代码示例与注释 七、总结 一、引言 在爬虫开发中&#xff0c;代理IP的使用是常见的做法&#xff0c;尤其在目标网站设置了反爬虫机制时。代理IP能够帮助爬虫…

小狐狸转账失败,提示gas费过高

做web3开发的时候&#xff0c;明明自己小狐狸里还有2.15的代币&#xff0c;但页面我要转出2.1的时候&#xff0c;明明是够的&#xff0c;而且使用小狐狸提示gas费用是21000&#xff0c;这已经是最小的了&#xff0c;但网页转出到其他账户总是提示失败。而且这个错误非常不好捕获…

二手车的一些经验

买辆二手车是怎样一种体验&#xff1f; - 知乎 买辆二手车是怎样一种体验&#xff1f; - 知乎 作者&#xff1a;jingangdaddy 链接&#xff1a;https://www.zhihu.com/question/28827207/answer/2881156930 来源&#xff1a;知乎 著作权归作者所有。商业转载请联系作者获得授…