C++——vector的了解与使用
目录
引言
vector容器的基本概念
1.功能
2.动态大小
3.动态扩展
vector的接口
1.vector的迭代器
2.vector的初始化与销毁
3.vector的容量操作
3.1 有效长度和容量大小
(1)使用示例
(2)扩容机制
3.2 有效长度和容量操作
(1)reserve
(2)resize
4.vector的访问操作
5.vector的修改操作
迭代器失效
结束语
引言
在我的博客 C++——string的了解和使用 中,我们学习了标准模板库(STL)中的string的一些基础内容,今天我们来学习 vector 。
vector容器的基本概念
在C++中,vector 是一个非常重要的容器,它属于标准模板库的一部分。vector 提供了一种动态数组的实现,可以在运行时动态地增加或减少其大小,同时保持元素的连续存储。
1.功能
vector是可变大小的序列容器,采用连续存储空间存储元素,可通过下标高效访问。
2.动态大小
与静态数组不同,vector 的大小可以在运行时动态地改变。此外,静态数组内数据通常存储在栈上,而vector中数据存储在堆上。
3.动态扩展
动态扩展的核心在于,当现有内存空间不足以满足需求时,不是简单地在原空间后续接新空间(这在连续内存分配中通常是不现实的,因为后续空间可能已被其他程序或数据占用),而是采取以下步骤:
(1)分配新空间:找到一个足够大的、连续的新内存空间。这个新空间的大小要能够容纳原数据和新数据。
(2)数据拷贝:将原内存空间中的数据复制到新分配的内存空间中。这个过程中需要确保数据的完整性和正确性。
(3)释放原空间:在数据成功拷贝到新空间后,释放原来的内存空间。这一步是为了避免内存泄漏。
(4)更新指针:将指向原内存空间的指针更新为指向新内存空间的指针。这样,程序就可以继续在新空间中操作数据。
此外,使用vector时必须包含头文件 #include<vector> 。
vector的接口
我们使用如下文档来辅助我们学习vector:
vector的接口详细介绍

1.vector的迭代器
与string一样,vector中也有迭代器。由于vector定义在vector类中,因此我们想要使用vector的迭代器需要通过域作用限定符访问——vector<类型>::iterator 。
其中,begin(),end(),rbeign(),rend()的使用访问方法与string中的类似,




我们来看看代码演示:
int main()
{vector<int> vec = { 0,1,2,3,4,5,6,7,8,9 };vector<int>::iterator it = vec.begin();cout << "顺序遍历:";while (it != vec.end()){cout << *it << " ";it++;}cout << endl;cout << "逆序遍历:";vector<int>::reverse_iterator rit = vec.rbegin();while (rit != vec.rend()){cout << *rit << " ";++rit;}return 0;
}
输出结果如下:

同样的,vector也支持const_iterator:
int main()
{vector<int> vec = { 0,1,2,3,4,5,6,7,8,9 };for (vector<int>::const_iterator it = vec.begin(); it != vec.end(); ++it) {std::cout << *it << " ";}std::cout << std::endl;return 0;
}
2.vector的初始化与销毁

vector 类的赋值运算符 operator= 被重载以支持将一个 vector 的内容复制到另一个 vector 中。

vector 支持多种构造函数,拷贝构造以及赋值运算符重载。
下面是一些简单的使用:
void printVector(vector<int>& vec)
{ for (vector<int>::iterator it = vec.begin(); it != vec.end(); ++it){cout << *it << " ";}cout << endl;
}int main()
{vector<int> vec1; for (int i = 0; i < 5; ++i){vec1.push_back(i);}vector<int> vec2(vec1.begin(), vec1.end()); vector<int> vec3(5, 5); vector<int> vec4(vec3); cout << "打印vec2: ";printVector(vec2);cout << "打印vec3: ";printVector(vec3);cout << "打印vec4: ";printVector(vec4);return 0;
}
输出结果为:

int main()
{vector<int> vec1, vec2;for (int i = 0; i < 5; i++){vec1.push_back(i);}vec2 = vec1;printVector(vec2);return 0;
}
输出结果为:

3.vector的容量操作
如下表格是关于vector的一些基础的容量操作:
| 函数名称 | 功能 |
| size | 返回vector的有效长度 |
| capacity | 返回vector的容量大小 |
| clear | 清空vector |
| empty | 检查vector是否为空,是则返回ture,否则返回false |
| reserve | 请求改变vector的容量 |
| resize | 重新设置有效元素的数量,超过原来有效长度则用c字符填充 |
3.1 有效长度和容量大小
(1)使用示例
与 string类 类似,我们可以使用 size()返回容器的有效长度;capacity()返回容器的容量大小。
下面是简单的测试用例:
int main()
{vector<int> vec = { 0,1,2,3,4,5,6,7,8,9 };cout << vec.size() << endl;cout << vec.capacity() << endl;if (vec.empty()){cout << "vec为空" << endl;}else{cout << "vec不为空" << endl;}vec.clear();if (vec.empty()){cout << "vec为空" << endl;}else{cout << "vec不为空" << endl;}return 0;
}
输出结果为:

通常来说,vector的有效长度和容量大小相同
(2)扩容机制
接下来我们来看看vector的扩容机制:
int main()
{size_t sz;vector<int> vec;sz = vec.capacity();cout << "making vec grow:" << endl;for (int i = 0; i < 100; ++i){vec.push_back(i);if (sz != vec.capacity()){sz = vec.capacity();cout << "capacity changed: " << sz << endl;}}
}
输出结果为:

在vs2022中,vector是以1.5倍进行扩容处理的,
我们现在把这段代码放到g++中运行看看:

我们可以看到,在此环境中,vector是以二倍进行扩容的。
3.2 有效长度和容量操作
接下来我们来学习vector中的reserve和resize(这俩函数的使用与string中的差不多)。
(1)reserve
reserve 函数用于请求改变容器的容量,即分配足够的内存空间以容纳至少指定数量的元素

简单使用一下:
int main()
{vector<int> vec;vec.reserve(10);cout << vec.capacity() << endl;return 0;
}
输出结果为:

(2)resize

resize的使用有如下两种:
resize(int num);
如果 num 小于当前容器的大小,那么容器末尾的多余元素将被删除。如果 num 大于当前容器的大小,则容器将被扩展,新添加的元素将被初始化为该类型的默认值(对于内置类型如 int,默认值为 0)。
resize(int num, int elem);
这个方法同样用于将 std::vector 的大小调整为 num,但在容器需要扩展时,新添加的元素将被初始化为 elem 而不是默认值。如果 num 小于当前容器的大小,多余元素的处理方式与第一个 resize 方法相同,即被删除。
简单的使用一下:
int main()
{vector<int> vec = { 1,2,3,4,5 };vec.resize(3);for (int i = 0; i < vec.size(); i++){cout << vec[i] << " ";}cout << endl;vec.resize(4);for (int i = 0; i < vec.size(); i++){cout << vec[i] << " ";}cout << endl;vec.resize(5, 9);for (int i = 0; i < vec.size(); i++){cout << vec[i] << " ";}cout << endl;return 0;
}
输出结果为:

4.vector的访问操作
vector的访问操作有如下几个:
| 函数名称 | 功能 |
| operator[] | 返回指定位置的元素,越界则报错 |
| at | 返回指定位置的元素,越界则抛异常 |
| front | 返回字符串第一个元素 |
| back | 返回字符串最后一个元素 |




这些函数的用法也与string中的函数用法差不多,就不多介绍了,来看看代码:
int main()
{vector<int> vec = { 0,1,2,3,4,5,6,7,8,9 };for (int i = 0; i < vec.size(); i++){cout << vec[i] << " ";}cout << endl;for (int i = 0; i < vec.size(); i++){cout << vec.at(i) << " ";}cout << endl;cout << "front:" << vec.front() << endl;cout << "back:" << vec.back() << endl;return 0;
}
输出结果为:

5.vector的修改操作
vector的修改操作有如下几个:
| 函数名称 | 功能 |
| push_back | 在数组后追加元素 |
| pop_back | 删除数组最后一个元素 |
| insert | 在指定位置追加元素 |
| assign | 使用指定数组替换原数组 |
| erase | 删除数组指定部分区间 |
| swap | 交换两个数组 |
先来看看push_back(),pop_back(),assign(),swap() :




int main()
{vector<int> vec1 = { 0,1,2,3,4,5,6,7,8,9 };cout << "back:" << vec1.back() << endl;// 元素尾插vec1.push_back(10);// 元素尾删cout << "back:" << vec1.back() << endl;vec1.pop_back();cout << "back:" << vec1.back() << endl;vector<int> vec2 = { 9,9,9,9,9 };vec2.assign(3, 3);for (int i = 0; i < vec2.size(); i++){cout << vec2[i] << " ";}cout << endl;vec2.swap(vec1);for (int i = 0; i < vec1.size(); i++){cout << vec1[i] << " ";}cout << endl;for (int i = 0; i < vec2.size(); i++){cout << vec2[i] << " ";}cout << endl;return 0;
}
输出结果如下:

我们再来看看insert和erase:
insert函数:

来看代码:
int main()
{vector<int> vec1(5, 10);vector<int>::iterator it = vec1.begin();it = vec1.insert(it, 100);cout << "vec1:";for (it = vec1.begin(); it < vec1.end(); it++){cout << *it << " ";}cout << endl;vec1.insert(it, 2, 1000);it = vec1.begin();cout << "vec1:";for (it = vec1.begin(); it < vec1.end(); it++){cout << *it << " ";}cout << endl;vector<int> vec2(2, 10000);it = vec1.begin();vec1.insert(it + 2, vec2.begin(), vec2.end());cout << "vec1:";for (it = vec1.begin(); it < vec1.end(); it++){cout << *it << " ";}cout << endl;return 0;
}
输出结果为:

erase函数:

简单的代码演示如下:
int main()
{vector<int> vec = { 0,1,2,3,4,5,6,7,8,9 };vector<int>::iterator it = vec.erase(vec.begin() + 3); // 删除值为3的元素it = vec.erase(it); // 删除值为4的元素for (int i = 0; i < vec.size(); i++){cout << vec[i] << " ";}cout << endl;it = vec.erase(vec.begin(), vec.begin() + 5);for (int i = 0; i < vec.size(); i++){cout << vec[i] << " ";}cout << endl;return 0;
}
输出结果为:

迭代器失效
迭代器的主要作用就是让算法能够不用关心底层数据结构,其底层实际就是一个指针,或者是对 指针进行了封装,比如:vector的迭代器就是原生态指针T* 。因此迭代器失效,实际就是迭代器 底层对应指针所指向的空间被销毁了,而使用一块已经被释放的空间,造成的后果是程序崩溃(即 如果继续使用已经失效的迭代器,程序可能会崩溃)。
以下可能会导致迭代器失效:
1.会引起其底层空间改变的操作,都有可能使迭代器失效
int main()
{vector<int> v{ 1,2,3,4,5,6 };auto it = v.begin();// 将有效元素个数增加到100个,多出的位置使用8填充,操作期间底层会扩容// v.resize(100, 8);// reserve的作用就是改变扩容大小但不改变有效元素个数,操作期间可能会引起底层容量改变// v.reserve(100);// 插入元素期间,可能会引起扩容,而导致原空间被释放// v.insert(v.begin(), 0);// v.push_back(8);// 给vector重新赋值,可能会引起底层容量改变//v.assign(100, 8);/*出错原因:以上操作,都有可能会导致vector扩容,也就是说vector底层原理旧空间被释放掉,而在打印时,it还使用的是释放之间的旧空间,在对it迭代器操作时,实际操作的是一块已经被释放的空间,而引起代码运行时崩溃。解决方式:在以上操作完成之后,如果想要继续通过迭代器操作vector中的元素,只需给it重新赋值即可。 */while (it != v.end()){cout << *it << " ";++it;}cout << endl;return 0;
}
2.指定位置元素的删除操作--erase
int main()
{int a[] = { 1, 2, 3, 4 };vector<int> v(a, a + sizeof(a) / sizeof(int));// 使用find查找3所在位置的iteratorvector<int>::iterator pos = find(v.begin(), v.end(), 3);// 删除pos位置的数据,导致pos迭代器失效。v.erase(pos);cout << *pos << endl; // 此处会导致非法访问return 0;
}
3.与vector一样,string在插入+扩容操作+erase之后,迭代器也会失效
int main()
{string s("hello");auto it = s.begin();// 放开之后代码会崩溃,因为resize到20会string会进行扩容// 扩容之后,it指向之前旧空间已经被释放了,该迭代器就失效了// 后序打印时,再访问it指向的空间程序就会崩溃//s.resize(20, '!');while (it != s.end()){cout << *it;++it;}cout << endl;it = s.begin();while (it != s.end()){it = s.erase(it);// 按照下面方式写,运行时程序会崩溃,因为erase(it)之后// it位置的迭代器就失效了// s.erase(it); ++it;}return 0;
}
结束语
写完啦~\(≧▽≦)/~
接下来会愈加忙碌,希望自己还能挤出时间写博客=_=
感谢各位大佬的支持!!!
求点赞收藏评论关注!!!
相关文章:
C++——vector的了解与使用
目录 引言 vector容器的基本概念 1.功能 2.动态大小 3.动态扩展 vector的接口 1.vector的迭代器 2.vector的初始化与销毁 3.vector的容量操作 3.1 有效长度和容量大小 (1)使用示例 (2)扩容机制 3.2 有效长度和容量操作 (1)reserve (2)resize 4.vector的访问操作…...
Ubuntu设置静态IP地址
Ubuntu如果是最小安装,没有图形界面,需要配置静态IP,该怎么操作呢? Netplan 是最新版 Ubuntu 的默认网络管理工具。Netplan 的配置文件使用 YAML 编写,扩展名为 .yaml。 注意:配置文件中的空格是语法的一部…...
力扣349.两个数组的交集
题目链接:349. 两个数组的交集 - 力扣(LeetCode) 给定两个数组 nums1 和 nums2 ,返回 它们的 交集。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。 示例 1: 输入:nums1 [1,2,…...
FreeRTOS - 软件定时器
在学习FreeRTOS过程中,结合韦东山-FreeRTOS手册和视频、野火-FreeRTOS内核实现与应用开发、及网上查找的其他资源,整理了该篇文章。如有内容理解不正确之处,欢迎大家指出,共同进步。 1. 软件定时器 软件定时器也可以完成两类事情…...
Python的Atlassian第三方库的详细介绍
atlassian-python-api 是一个用于与 Atlassian 生态系统进行交互的 Python 库,支持与多种 Atlassian 工具(如 Jira、Confluence、Bitbucket 等)进行 API 调用。它简化了 REST API 的调用,提供了高层次的抽象,方便开发者…...
Java中的基本循环结构详解
在Java编程中,循环是控制流的重要组成部分,用于重复执行一段代码。Java提供了三种基本的循环结构:for循环、while循环和do-while循环。本文将详细介绍这三种循环的语法和使用场景,并通过示例代码展示其应用。 一,for …...
关于Git Bash中如何定义alias
一、在一次临时Bash会话中使用alias 在Bash中直接输入alias xxdddd,xx为对应要执行的命令的缩写,dddd为要执行的命令,如alias ddcd /d,输入完成后,在Bash中输入dd,即可切换至D盘。 此种设置方式ÿ…...
luckfox1106初次使用
luckfox1106初次使用 下载rk驱动 https://files.luckfox.com/wiki/Luckfox-Pico/Software/DriverAssitant_v5.12.zip 安装驱动 SD 卡烧录工具 https://files.luckfox.com/wiki/Luckfox-Pico/Software/SocToolKit_v1.98_20240705_01_win.zip 右键以管理员方式运行...
ab命令深入解析:ApacheBench性能测试工具
软考鸭微信小程序 学软考,来软考鸭! 提供软考免费软考讲解视频、题库、软考试题、软考模考、软考查分、软考咨询等服务 引言 在Web开发和运维领域,性能测试是评估服务器和应用性能的重要手段。ApacheBench(简称ab)是Apache HTTP服务器自带的…...
VSCode创建VUE项目(二)前端登录页面
一.创建登录页面 代码: <template><div class"login-container dis-h"><div class"login-form dis-h"><div class"dis-v left"><span> 欢迎~ </span><span> VUE 新世界 </span>&l…...
centos 8.4学习小结
1.权限委派 2.vim快捷方式 2.1非正常关闭文本处理方式 2.2快捷方式 2.3TAB键补齐安装包 [ rootcloud Packages]# rpm -ivh bash-completion-2.7-5.el8.noarch.rpm 2.4#history 查询历史记录 [rootcloud ~]# vim /etc/profile HISTSIZE1000(默认保存1000条历史记…...
AI 设计工具合集
🐣个人主页 可惜已不在 🐤这篇在这个专栏AI_可惜已不在的博客-CSDN博客 🐥有用的话就留下一个三连吧😼 前言: AI 视频,科技与艺术的精彩融合。它借助先进的人工智能技术,为影像创作带来全新可能。本书…...
mac 源代码安装openresty
1. clone源代码 git clone https://github.com/openresty/openresty.git 2. 安装依赖包 brew install hg unix2dos brew install pcre openssl 3. 编译 make 4. 安装openresty cd openresty-1.27.1.1 ./configure --prefix/opt/openresty --with-http_ssl_module --with-…...
人工智能和机器学习之线性代数(二)
人工智能和机器学习之线性代数(二) 本文Linear Algebra 101 for AI/ML – Part 2将通过介绍向量的点积(dot Product)、Embedding及其在相似性搜索中的应用来建立这些基础知识。 将学习Embedding,Embedding是表示概念、对象和想法的特殊类型的向量。Embedding在整个…...
Postman中的form-data 和 JSON 的区别
在使用 Postman 进行 API 测试时,form-data 和 JSON 是两种常用的请求体格式,它们有以下几个主要区别: 1. 数据格式 form-data: 主要用于表单数据的提交,适合文件上传和键值对的数据传递。数据以键值对的形式编码,类似…...
网络安全基础知识点_网络安全知识基础知识篇
文章目录 一、网络安全概述1.1 定义1.2 信息安全特性1.3 网络安全的威胁1.4 网络安全的特征 二、入侵方式2.1 黑客2.1.1 入侵方法2.1.2 系统的威胁2.2 IP欺骗与防范2.2.1 TCP等IP欺骗基础知识2.2.2 IP欺骗可行的原因2.2.3 IP欺骗过程2.2.4 IP欺骗原理2.2.5 IP欺骗防范2.3 Sniff…...
Vue.js 从入门到精通:全面解析组件化、路由与状态管理(附 Todo 案例)
在当今的前端开发领域,Vue.js 以其简洁、高效和灵活的特点受到了广泛的关注和应用。本文将带你从 Vue 的基础知识入手,逐步深入到高级特性,让你对 Vue 有一个全面的了解,并通过实际案例帮助你更好地掌握 Vue 的开发。 一、Vue 简…...
AI Weekly#1:过去一周重要的AI资讯汇总
🚀热点头条 诺贝尔奖青睐AI领域:2024年诺贝尔物理学奖和化学奖均授予了与人工智能相关的研究。物理学奖颁发给了约翰霍普菲尔德和杰弗里辛顿,表彰他们在机器学习领域的开创性工作。化学奖则授予了大卫贝克、德米斯哈萨比斯和约翰江珀…...
图论刷题
卡码网 98. 所有可达路径 使用邻接矩阵存储: #include<iostream> #include<vector> using namespace std;vector<vector<int>>res;//收集符合条件的路径vector<int>path;//0节点到终点的路径//确定递归函数 参数和返回值void dfs(c…...
ICM20948 DMP代码详解(85)
接前一篇文章:ICM20948 DMP代码详解(84) 上一回解析了inv_icm20948_ctrl_enable_sensor函数的大部分代码,只剩下一行代码没有解析。为了便于理解和回顾,再次贴出inv_icm20948_ctrl_enable_sensor函数源码,在EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948Data…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
C++.OpenGL (20/64)混合(Blending)
混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...
在golang中如何将已安装的依赖降级处理,比如:将 go-ansible/v2@v2.2.0 更换为 go-ansible/@v1.1.7
在 Go 项目中降级 go-ansible 从 v2.2.0 到 v1.1.7 具体步骤: 第一步: 修改 go.mod 文件 // 原 v2 版本声明 require github.com/apenella/go-ansible/v2 v2.2.0 替换为: // 改为 v…...
如何在Windows本机安装Python并确保与Python.NET兼容
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
