vector讲解
在学习玩string后我们开始学习vector,本篇博客将对vector进行简单的介绍,还会对vector一些常用的函数进行讲解
vector的介绍
实际上vector就是一个数组的数据结构,但是vector是由C++编写而成的,他和数组也有本质上的区别,但也有相同点,他的特征概括如下:
- vector是表示可变大小数组的序列容器。
- 就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。
- 本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小为了增加存储空间。其做法是,分配一个新的数组,然后将全部元素移到这个数组。就时间而言,这是一个相对代价高的任务,因为每当一个新的元素加入到容器的时候,vector并不会每次都重新分配大小。
- vector分配空间策略:vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是对数增长的间隔大小,以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。
- 因此,vector占用了更多的存储空间,为了获得管理存储空间的能力,并且以一种有效的方式动态增长。
- 与其它动态序列容器相比(deque, list and forward_list), vector在访问元素的时候更加高效,在末尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。比起list和forward_list统一的迭代器和引用更好。
对于C语言中的数组,二者有很多的异同点,我将其概括如下:
相同点:
1 二者都是采用连续的空间来存储元素
2 二者都能通过下标进行访问
不同点:
1 vector是采用动态开辟,容器大小可以动态改变,并且是自动处理
2vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存储空间更大
vector的使用
vector的定义
vector的定义就差不多是初始化以及拷贝构造和构造,这些在之前的string类函数讲解中也提到了,其实都大差不差的

构造并初始化:
第一个参数是你要初始化元素的个数,第二个参数是你要初始化成的字符
这里需要注意**<>里面就是你要放入vector里元素的类型**
vector<int> v(10, 1);
for (auto ch : v)
{cout << ch;
}
cout << endl;

拷贝构造:
其实都大差不差,学习了前面的string和类和对象后都很简单了
vector<int> v(10, 1);vector<int> v1(v);for (auto ch : v1){cout << ch;}cout << endl;

vector iterator 的使用
迭代器很常用,咱们做个简单的讲解

迭代器同样地分为正向和反向:
我们可以通过一个简单的代码来了解迭代器的使用
vector<int> v;
for (int i = 1; i <= 5; i++)
{v.push_back(i);
}
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{cout<< ' ' << *it;
}
cout << endl;

下面为反向迭代器:
反向迭代器记得加上reverse
vector<int> v;
for (int i = 1; i <= 5; i++)
{v.push_back(i);
}
for (vector<int>::reverse_iterator it = v.rbegin(); it != v.rend(); it++)
{cout<< ' ' << *it;
}
cout << endl;

关于begin和rbegin,end和rend的位置的关系如下图所示,我们要记得,两种迭代器都是从begin开始遍历:
通过这张图,我们需要注意到一个很重要的点:
迭代器的区间都是左闭右开的!所以end是在最后一个元素的后一个位置!

vector 空间增长问题

其实空间增长问题我在之前的string类就有提到过,都是有规律可循的:
1 capacity的代码在vs和g++下分别运行会发现,vs下capacity是按1.5倍增长的,g++是按2倍增长的。vector增容都是2倍,具体增长多少是根据具体的需求定义
2 reserve只负责开辟空间,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问题。
3 resize在开空间的同时还会进行初始化,影响size
可以看到,resize默认就是初始化为0:
同时改变了capacity和size

而reserve只改变了capacity,并且不会有初始化的功能:
vector<int> v;
v.reserve(10);
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{cout<< ' ' << *it;
}
cout << endl;
cout << "former:" << endl;
cout << v.size() << endl;
cout << v.capacity() << endl;
v.reserve(20);
cout << endl;
cout << "after:" << endl;
cout << v.size() << endl;
cout << v.capacity() << endl;

vector 增删查改

pushback尾插和popback尾删:
都很简单,拿一段简单的代码来演示一下吧:
vector<int> v;
v.resize(10,1);
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{cout<< ' ' << *it;
}
cout << endl;
v.push_back(2);
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{cout << ' ' << *it;
}
cout << endl;
v.pop_back();
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{cout << ' ' << *it;
}
cout << endl;

insert插入函数:
这里如果需要在其他地方插入就在begin上进行+操作
vector<int> v;
v.resize(10,1);
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{cout<< ' ' << *it;
}
cout << endl;
vector<int>::iterator it = v.begin();
v.insert(it, 3);
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{cout << ' ' << *it;
}
cout << endl;

erase函数:
erase函数可以根据下标索引来删除元素,但是再insert后要重新给下标赋值,insert前的下标i已经失效了,其实这就是所说的:迭代器失效问题!
在这里我们插入了元素后会发生扩容,原空间可能已经被释放了(或者说如果erase删除了最后一个位置的元素,vector里已经没有元素可以删除,也会导致迭代器失效),但是erase后我们又使用it打印,这里的it可能使用的就是原空间,程序就会发生崩溃,所以我们需要在执行完insert后再次对it进行赋值,不然就会发生这种情况(但是一些编译器对于迭代器失效没有过于严格的检查,所以程序不会崩溃,但是程序输出的结果不对):
erase函数返回的是在vector对象中删除元素的后一个元素的指针!

通常解决迭代器失效最简单的方法就是:
对迭代器重新赋值
vector<int> v;
v.resize(10,1);
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{cout<< ' ' << *it;
}
cout << endl;
vector<int>::iterator i = v.begin();
v.insert(i+3, 3);
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{cout << ' ' << *it;
}
cout << endl;
i = v.begin();
v.erase(i+3);
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{cout << ' ' << *it;
}
cout << endl;

swap函数:
我们通过一段简单的代码来了解一下:
我们交换前打印两个vector对象中的元素,交换后再打印一次
vector<int> v1;
v1.resize(10,1);
cout << "交换前" << endl;
cout << "v1:";
for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++)
{cout<< ' ' << *it;
}
cout << endl;
vector<int> v2;
v2.resize(10, 2);
cout << "v2:";
for (vector<int>::iterator it = v2.begin(); it != v2.end(); it++)
{cout << ' ' << *it;
}
cout << endl;
v1.swap(v2);
cout << "交换后" << endl;
cout << "v1:";
for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++)
{cout << ' ' << *it;
}
cout << endl;
cout << "v2:";
for (vector<int>::iterator it = v2.begin(); it != v2.end(); it++)
{cout << ' ' << *it;
}
cout << endl;

好了,今天的分享到这里就结束了,谢谢大家的支持!
相关文章:
vector讲解
在学习玩string后我们开始学习vector,本篇博客将对vector进行简单的介绍,还会对vector一些常用的函数进行讲解 vector的介绍 实际上vector就是一个数组的数据结构,但是vector是由C编写而成的,他和数组也有本质上的区别ÿ…...
nvm 配置淘宝镜像失效,以及安装node后 npm-v 无效
win11 nvm版本 1.1.4 和1.1.7和1.1.12(目前最新版本24年 一月二十三日) 以上nvm版本都会出现一下问题, 从https://github.com/coreybutler/nvm-windows/releases 下载nvm安装包如下图 傻瓜式安装后,不用去配置环境变量&#…...
【Android Gradle 插件】Gradle 基础配置 ④ ( Gradle Wrapper 配置作用 | Gradle 下载的依赖库存放位置 )
一、Gradle Wrapper 配置作用 gradle wrapperdistributionBaseGRADLE_USER_HOME distributionPathwrapper/dists distributionUrlhttps\://services.gradle.org/distributions/gradle-6.7.1-bin.zip zipStoreBaseGRADLE_USER_HOME zipStorePathwrapper/distsGradle Wrapper 配…...
Deepin_Ubuntu_查看树形目录结构(tree)
Linux系统(Deepin、Ubuntu)中,可以使用tree命令来查看树形目录结构,下面是一些示例: 查看当前目录的树形结构: tree查看指定目录的树形结构,例如/etc/X11/fonts目录: tree /etc/X…...
Java Excel分割成许多小文件
最近在处理excel,数据很多,需要将excel拆分成许多小块,并保留原来的格式,于是写了该算法,并能保留原来的样式,使用很简单: Sheet splitSheet ExcelUtil.split(sheet, 0, 20, 5, 8); 传入开始…...
【心得】java从CC1链入门CC链个人笔记
来劲了,感觉离真正的CTF又近了一步。 本文仅从一个萌新的角度去谈,如有纰漏,纯属蒟蒻。 目录 CC链概念 CC链学习前置知识 CC1链 Version1 Version2 Version3 CC链概念 CC链 Commons Collections apache组织发布的开源库 里面主要对…...
Django migration 新增外键的坑
TL;DR 永远不要相信 makemigrations! migrate 之前一定好好看看 migrate 了啥东西,必要时手动修改生成的 migrate 文件。 最好把db的更新与服务代码更新解耦 场景 先描述下场景: 现在有两个表,一个是 question,一…...
相关系数(皮尔逊相关系数和斯皮尔曼相关系数)
本文借鉴了数学建模清风老师的课件与思路,可以点击查看链接查看清风老师视频讲解:5.1 对数据进行描述性统计以及皮尔逊相关系数的计算方法_哔哩哔哩_bilibili 注:直接先看 ( 三、两个相关系数系数的比较 ) 部分&#x…...
了解 Vite 插件
众所周知 Vite 是基于 Rollup 的构建工具,Vite 插件为了优化、扩展项目构建系统功能的工具。 比如 vite-plugin-eslint 为我们提供了代码分析的功能,帮助我们在开发过程中的风格一致性。 简单示例 本文中的示例是基于 Vite Vue3.x TypeScript 来实现…...
算法竞赛基础:C++双向链表的结构和实现(普通链表、List、静态链表)
算法竞赛基础:双向链表 本文将会介绍在算法竞赛中双向链表的几种使用方式,适合有一定基础的人阅读。 双向链表的结构 一般来说,普通的链表结构是这样的: struct node {int num;node *next; }next指针指向下一个链表ÿ…...
openssl3.2/test/certs - 019 - ca-nonca trust variants: +serverAuth, +anyEKU
文章目录 openssl3.2/test/certs - 019 - ca-nonca trust variants: serverAuth, anyEKU概述笔记 ca-nonca.pem from exp 016openssl3.2/test/certs - 019 - ca-nonca trust variants: serverAuth, anyEKUEND openssl3.2/test/certs - 019 - ca-nonca trust variants: serverAu…...
Unity SRP 管线【第五讲:URP烘培光照】
本节,我们将跟随数据流向讲解UEP管线中的烘培光照。 文章目录 一、URP烘培光照1. 搭建场景2. 烘培光照参数设置MixedLight光照设置:直观感受 Lightmapping Settings参数设置: 3. 我们如何记录次表面光源颜色首先我们提取出相关URP代码&#…...
Mysql运维篇(一) 日志类型
一路走来,所有遇到的人,帮助过我的、伤害过我的都是朋友,没有一个是敌人,如有侵权请留言,我及时删除。 一、mysql相关日志 首先,我们能接触到的,一般我们排查慢查询时,会去看慢查询日志。如果做过数据备份会恢复的,可能接触或用过BinLog。那还有其他的吗?对MySQL原理…...
【C语言】结构体与内存操作函数 总结
结构体 一、结构体简介 C 语言内置的数据类型,除了最基本的几种原始类型,只有数组属于复合类型,可以同时包含多个值,但是只能包含相同类型的数据,实际使用中并不够用。 实际使用中,主要有下面两种情况&a…...
第12章_集合框架(Collection接口,Iterator接口,List,Set,Map,Collections工具类)
文章目录 第12章_集合框架本章专题与脉络1. 集合框架概述1.1 生活中的容器1.2 数组的特点与弊端1.3 Java集合框架体系1.4 集合的使用场景 2. Collection接口及方法2.1 添加2.2 判断2.3 删除2.4 其它 3. Iterator(迭代器)接口3.1 Iterator接口3.2 迭代器的执行原理3.3 foreach循…...
C语言进阶——数据结构之链表(续)
前言 hello,大家好呀,我是Humble,本篇博客承接之前的C语言进阶——数据结构之链表 的内容(没看过的小伙伴可以从我创建的专栏C语言进阶之数据结构 找到那篇文章并阅读后在回来哦~),上次我们重点说了链表中…...
数据库课程设计-图书管理系统数据库设计
目录 一、实验目的 二、实验内容 三、实验要求 四、实验设计 4.1需求分析 4.1.1系统目标 4.1.2功能需求 4.1.3性能需求 4.14界面需求 4.2概念模型设计 4.2.1 实体及联系 4.2.2 E-R图 4.3 逻辑设计 4.3.1 E-R模型向关系模型的转换 4.3.2 数据库逻辑结构 4.3.3数据库模型函数依赖…...
【超简版,代码可用!】【0基础Python爬虫入门——下载歌曲/视频】
安装第三方模块— requests 完成图片操作后输入:pip install requests 科普: get:公开数据 post:加密 ,个人信息 进入某音乐网页,打开开发者工具F12 选择网络,再选择—>媒体——>获取URL【先完成刷新页面】 科…...
CommunityToolkit.Mvvm支持环境
引言 CommunityToolkit.Mvvm 包(又名 MVVM 工具包,以前称为 Microsoft.Toolkit.Mvvm)是一个现代、快速和模块化的 MVVM 库。 它是 .NET 社区工具包的一部分,其中一条原则是: 独立于平台和运行时 - .NET Standard 2.0…...
探讨品牌设计的本质,为企业形象注入活力!
品牌设计作为一个行业,首先需要明确行业的本质和意义。由于越来越多的咨询公司和营销公司对品牌有不同的理解和解释,因为他们服务的内容和专业水平不同,什么是品牌的定义越来越复杂,逐渐成为一种神秘的知识。例如,特劳…...
自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
Linux离线(zip方式)安装docker
目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...
Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
Go语言多线程问题
打印零与奇偶数(leetcode 1116) 方法1:使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...
Qt 事件处理中 return 的深入解析
Qt 事件处理中 return 的深入解析 在 Qt 事件处理中,return 语句的使用是另一个关键概念,它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别:不同层级的事件处理 方…...
rknn toolkit2搭建和推理
安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 ,不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源(最常用) conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...
Python常用模块:time、os、shutil与flask初探
一、Flask初探 & PyCharm终端配置 目的: 快速搭建小型Web服务器以提供数据。 工具: 第三方Web框架 Flask (需 pip install flask 安装)。 安装 Flask: 建议: 使用 PyCharm 内置的 Terminal (模拟命令行) 进行安装,避免频繁切换。 PyCharm Terminal 配置建议: 打开 Py…...
向量几何的二元性:叉乘模长与内积投影的深层联系
在数学与物理的空间世界中,向量运算构成了理解几何结构的基石。叉乘(外积)与点积(内积)作为向量代数的两大支柱,表面上呈现出截然不同的几何意义与代数形式,却在深层次上揭示了向量间相互作用的…...
