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

news2024/11/25 16:31:19

目录

前言:

 本篇文档图片引用自: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的底层模拟实现中涉及。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【随笔】Git 高级篇 -- 相对引用1 main^(十二)

&#x1f48c; 所属专栏&#xff1a;【Git】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大…

2023 年网络安全热点技术发展态势

文章目录 前言一、人工智能信息技术迎来井喷式发展期二、零信任网络安全架构即将投入实际部署三、美国全面推动军政业务向云环境迁移四、专用太空软硬件与独立卫星网络并行发展五、量子信息技术与网络安全领域加速融合前言 在 2023 年取得进展的信息技术不在少数。从网络安全的…

【opencv】示例-distrans.cpp 距离变换

stuff.jpg #include <opencv2/core/utility.hpp> // 包含OpenCV中的核心功能支持库 #include "opencv2/imgproc.hpp" // 包含OpenCV中的图像处理库 #include "opencv2/imgcodecs.hpp" // 包含OpenCV中的图像编解码库 #include "open…

微信小程序picker设置了系统年度,打开选择年份从1年开始显示

背景&#xff1a;开发微信小程序时&#xff0c;使用了picker组件&#xff0c;设置值为当前系统时间年份&#xff0c;可以正常回显年份。但是打开面板选择年份的时候&#xff0c;默认从一年开始显示的。如下图所示。 原因&#xff1a;因为绑定的年份字段为Number类型。 解决方案…

App Inventor 2 怎么判断两个颜色是否相等?

问&#xff1a;为什么这里不能判断这个背景颜色呢&#xff1f; 答&#xff1a;背景颜色不是 bool 型&#xff0c;不能直接插入判断积木。 本帖隐藏的内容 要使用 等于&#xff08;推荐数学块.等于&#xff0c;当然文本块.等于也可以&#xff09; 来判断才行。 经检验&…

java错误记录

文章目录 javaslf4j中log不存在 maven编译出现Non-resolvable import POM: Failure to find类找不到jdk版本不对 java slf4j中log不存在 解决方法&#xff1a;再idea中安装lombok插件。 离线下载地址 https://github.com/mplushnikov/lombok-intellij-plugin/releases&#x…

爬虫 selenium

爬虫 selenium 【一】介绍 【1】说明 Selenium是一款广泛应用于Web应用程序测试的自动化测试框架 它可以模拟用户再浏览器上的行为对Web应用进行自动化测试 主要作用&#xff1a; 浏览器控制&#xff1a;启动、切换、关闭不同浏览器元素定位于操作&#xff1a;通过CSS选择器…

突破编程_前端_SVG(概述)

1 什么是 SVG SVG&#xff0c;全称可缩放矢量图形&#xff08;Scalable Vector Graphics&#xff09;&#xff0c;是一种基于 XML&#xff08;可扩展标记语言&#xff09;的矢量图像格式。这种图像格式的主要特点是它描述的是矢量图形&#xff0c;而不是基于像素的位图图像。因…

计数排序解读

当我们提及排序算法时&#xff0c;通常会想到冒泡排序、选择排序、插入排序、归并排序和快速排序等经典算法。然而&#xff0c;今天我们要探讨的是一种非比较型整数排序算法——计数排序。计数排序在某些特定场景下表现出色&#xff0c;具有线性的时间复杂度。下面我们将深度剖…

如何看待现在的前端?必备技能和方向?

​ 目录 1. 技术生态丰富 2. 用户体验为中心 3. 跨平台和移动优先 4. 性能和安全性 5. 前端工程化和自动化 6. 服务端渲染和静态站点生成 7. 人工智能和机器学习的融合 总结 发展方向&#xff1a; 必备技能&#xff1a; 当前前端开发领域正在经历快速的发展和变革。…

Three飞线动画(运动轨迹)

效果图 1.初始化场景 onMounted(() > {line() })let index 0; //取索引值的点的位置 let num 20; //从曲线上获取的数量 let points1, newLine1, bufferGeometry1; let points2, newLine2, bufferGeometry2;function line() {} 2.场景中加入一条三维曲线 function line…

Flody算法求解多源最短路问题

Flody算法求解多源最短路问题 蓝桥公园 #include <bits/stdc.h> using namespace std; #define int long long const int N409; int n,m,q,d[N][N]; signed main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>n>>m>>q;memset(d,0x3f,sizeof…

Linux网卡与IP地址:通往网络世界的通行证

在探索Linux网卡和IP地址的关系之前&#xff0c;我们得先理解Linux网卡是怎么工作的。想象一下&#xff0c;每台计算机都是一个世界&#x1f30e;&#xff0c;而网卡就是连接这些世界的门户&#x1f6aa;。网卡的工作就是接收和发送数据包&#xff0c;就像邮差&#x1f4ec;递送…

在win10上虚拟一个LoongOS系统(类似虚拟机)作为开发环境

文章目录 1.安装1.1.下载这三个东西1.2.安装好qemu。1.3.创建一个启动脚本startup_mate.bat&#xff0c;然后把三部分东西放到一起1.4.然后双击startup.bat就可以启动了。 2.文件的传输2.1.使能虚拟机系统的ssh2.2.连接ssh 3.Qt相关安装Qt安装opencv 1.安装 注意&#xff0c;一…

揭秘操作系统:核心功能与Linux系统解析

1.引言 在先前探讨中&#xff0c;我们了解到计算机主机内部的硬件资源需要一种高效管控手段&#xff0c;由此催生了操作系统的诞生。操作系统&#xff08;Operating System&#xff0c;简称OS&#xff09;&#xff0c;是计算机生态系统中不可或缺的核心组件&#xff0c;以其复杂…

高颜值高性能的开源免费自托管照片和视频备份方案:Immich

Immich&#xff1a;安全存储您的珍贵记忆&#xff0c;高颜值且高性能的自托管照片与视频备份解决方案&#xff0c;让您随时随地无忧回顾美好时光。- 精选真开源&#xff0c;释放新价值。 概览 在数字化时代&#xff0c;我们的照片和视频越来越多&#xff0c;如何安全、有效地备…

DSP笔记12-PWM基础知识及EPWM

PWM pulse width modulation 脉冲宽度调制&#xff0c;宽度可调节的方波脉冲&#xff0c;驱动开关器件&#xff0c; 参数&#xff1a; 1.频率f 1kHz&#xff0c;2kHz开关损耗 2.周期T 3.幅值&#xff0c;高低电平之间电压 gpio输出3.3V&#xff0c;转换成5V高电平输出 4.占…

Vue项目中,使用高级表格vxe-table中的【vxe-grid】动态列之动态插槽

1、首先项目当中得安装了vxe-table // 没有安装的话&#xff0c;可以使用一下命令安装 npm install vxe-table 或 yarn add vxe-table使用示例&#xff1a; import Vue from vue import VXETable from vxe-table import vxe-table/lib/style.cssVue.use(VXETable)2、动态列中动…

苍穹外卖---文件上传-阿里OSS

一&#xff1a;开通阿里云对象存储服务oss,创建bucket&#xff0c;获得密钥 二&#xff1a;在程序中集成上传文件功能 1.连接阿里云OSS对象存储服务器 声明一个配置属性的文件用于传入连接的参数 package com.sky.properties;import lombok.Data; import org.springframewo…

电感在 DC/DC 变换器中的作用及选型指南

消费类应用是现代 DC/DC 变换器需求的主要驱动力。在这类应用中&#xff0c;功率电感主要被用于电池供电设备、嵌入式计算&#xff0c;以及高功率、高频率的 DC/DC 变换器。了解电感的电气特性对于设计紧凑型、经济型、高效率、并具备出色散热性能的系统至关重要。 电感是一种…