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的底层模拟实现中涉及。

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

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

相关文章

[C#]OpenCvSharp利用MatchTemplate实现多目标匹配

【效果展示】 原图 模板图 匹配结果&#xff1a; 【实现部分代码】 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using…

单链表专题

文章目录 目录1. 链表的概念及结构2. 实现单链表2.1 链表的打印2.2 链表的尾插2.3 链表的头插2.4 链表的尾删2.5 链表的头删2.6 查找2.7 在指定位置之前插入数据2.8 在指定位置之后插入数据2.9 删除pos节点2.10 删除pos之后的节点2.11 销毁链表 3. 链表的分类 目录 链表的概念…

苹果电脑怎么彻底删除软件 苹果电脑卸载软件在哪里 cleanmymac x怎么卸载 mac废纸篓怎么删除

苹果电脑卸载软件的方法相对直观和简单&#xff0c;尤其是对于习惯使用Mac操作系统的用户来说。以苹果MacBook Pro为例&#xff0c;以下是卸载软件的详细步骤、使用方法、注意事项与建议。 一、卸载软件的详细步骤&#xff1a; 1. 打开Mac电脑&#xff0c;进入桌面&#xff0c…

React面试

React渲染流程(重点) jsx描述界面 jsx babel render function>vdom vdom fiber 在进行渲染 vdom 转换fiber reconcile 转换过程创建dom commit 到domvdom React Element 对象, 只记录了子节点, 没有记录兄弟节点, 因为渲染不可中断 fiber fiberNode 对象, 是一个链表 父节…

linux大文件IO

在Linux中处理大文件&#xff08;通常指大小超过2GB的文件&#xff09;时&#xff0c;需要使用特定的系统调用和标志&#xff0c;以确保程序能够正确地处理大文件的读写。这主要是因为在32位系统上&#xff0c;传统的文件偏移量和文件大小使用off_t类型表示&#xff0c;它通常是…

HarmonyOS 开发-MpChart运动健康场景实践案例

介绍 MpChart是一个包含各种类型图表的图表库&#xff0c;主要用于业务数据汇总&#xff0c;例如销售数据走势图&#xff0c;股价走势图等场景中使用&#xff0c;方便开发者快速实现图表UI&#xff0c;MpChart主要包括线形图、柱状图、饼状图、蜡烛图、气泡图、雷达图、瀑布图…

GIF在线生成器

上传图片就能生成GIF的前端WEB工具 源码也非常简单 <!DOCTYPE html> <html lang"zh" class"dark"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1, m…

【opencv】示例-drawing.cpp画线、箭头、矩形、多边形、椭圆、圆形以及在图像上渲染文本并通过循环实现动态绘制效果...

#include "opencv2/core.hpp" // 引入opencv2核心头文件 #include "opencv2/imgproc.hpp" // 引入opencv2图像处理头文件 #include "opencv2/highgui.hpp" // 引入opencv2高级GUI(head-up display)头文件 #include <stdio.h> // 引入标准输…

生成随机图片验证码

随着互联网的不断发展&#xff0c;安全性问题日益突出。为了保障用户账号的安全性&#xff0c;很多网站都引入了验证码机制。验证码是一种区分用户是计算机还是人的公共全自动程序&#xff0c;可以有效防止恶意攻击和自动化脚本的滥用。本文将介绍如何使用Python生成随机图片验…

论文笔记:面向实体的多模态对齐与融合网络假新闻检测

整理了2022TMM期刊 Entity-Oriented Multi-Modal Alignment and Fusion Network for Fake News Detection&#xff09;论文的阅读笔记 背景模型改进的动态路由算法Cross-Modal Fusion 实验 背景 现有的假新闻方法对多模态特征进行各种跨模态交互和融合&#xff0c;在检测常见假…

MT3022 召唤神龙

思路&#xff1a;二分答案 。check():检查组p套卡是否成立&#xff0c;即检查r卡是否足够组成p套卡。 &#xff08;易错点&#xff1a;check的思路&#xff0c;开long long&#xff09; #include <bits/stdc.h> using namespace std; long long int n, m; long long int…

【VScode】同时编辑多处

【VScode】同时编辑多处 1. 多光标自定义批量编辑2. 选择多个&#xff0c;同时操作(批量选中局部匹配项)3. 取消选择4. 在不移动光标的情况下滚动屏幕5. 批量选中全局匹配项6.重点6.1 通过上下键选择多行6.2 同时选中所有行的末尾6.3 选中多列另一种方式6.4 通过正则的方式配置…

东方博宜 1582. 马里奥的银币2

东方博宜 1582. 马里奥的银币2 思路&#xff1a;这道题好简单~ 注意的点是 n/2 要记得变成浮点数 n/2.0 或者 n*1.0/2 #include<iostream> using namespace std; int main() {int a[1001] ;int n ;cin >> n ;for(int i 0 ; i < n ; i){cin >> a[i] ;}…

C++奇迹之旅:探索类对象模型内存的存储猜想

文章目录 &#x1f4dd;前言&#x1f320; 类的实例化&#x1f309;类对象模型 &#x1f320; 如何计算类对象的大小&#x1f309;类对象的存储方式猜想&#x1f320;猜想一&#xff1a;对象中包含类的各个成员&#x1f309;猜想二&#xff1a;代码只保存一份&#xff0c;在对象…

CST电磁仿真基本单位设置和保存结果【仿真教程】

保存结果的Result Navigator 积累的结果一目了然&#xff01; 用户界面上的Result Navigator 在一个仿真工程中更改变量取值进行仿真分析或者改变设置进行仿真分析时&#xff0c;之前的1DResult会不会消失呢&#xff1f; 1D Result&#xff1a;CST中1D Result指的是Y值取决…

VirusTaxo:病毒物种注释

https://github.com/omics-lab/VirusTaxo 安装 git clone https://github.com/omics-lab/VirusTaxo mamba create -n VirusTaxo python3.10 mamba activate VirusTaxo cd VirusTaxo python3 -m venv environment source ./environment/bin/activate pip install -r require…

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.占…

使用Springboot配置生产者、消费者RabbitMQ?

生产者服务 1、引入依赖以及配置rabbitmq 此时我们通过使用springboot来快速搭建一个生产者服务 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId> </dependency> applica…

规则引擎之LiteFlow应用

官网地址&#xff1a;LiteFlow DEMO 整体结构 1.引入maven依赖 <dependency><groupId>com.yomahub</groupId><artifactId>liteflow-spring-boot-starter</artifactId><version>2.11.4.2</version> </dependency> 2. 配置yml …

Linux--进程的概念(一)

目录 一、冯诺依曼体系结构二、操作系统2.1 什么是操作系统2.2 操作系统的意义 三、进程3.1 进程的基本概念3.2 描述进程——PCB3.3 进程和程序的区别3.4 task_struct-PCB的一种3.5 task_struct的内容分类 四、如何查看进程4.1 通过系统文件查看进程4.2 通过ps指令查看进程 五、…