C++:STL之vector

news2024/11/14 23:51:25

1.vector的使用

1.1vector的定义

使用vector需要包含头文件 #include<vector>

vector的构造
(constructor)构造函数声明接口说明
vector()  (重点)无参构造
vector(size_type n,const value_type& val = value_type())用n个val初始化并构造
vector(const vector& x) (重点)拷贝构造
vector(InputIterator first,InputIteator last)使用迭代器进行初始化构造
代码1:
int main()
{
	vector<int>  v1;//无参构造
	vector<int> v2(4, 1);//用4个1构造并初始化v2

	vector<int> v3(v2);//拷贝构造,拷贝v2给v3

	vector<int> v4(++v2.begin(), v2.end());//使用迭代器,将v2第二个元素到最后一个元素的值初始化v4
	return 0;
}

解析:从上面这张图可以看到我们首先使用无参构造了对象v1,接着用4个1构造并初始化对象v2,vector<int> 代表可以存储整形元素的一个对象

解析:从上图可知:我们使用拷贝构造函数对对象v3进行构造并初始化

解析:从上图可知:我们使用迭代器将v2第二个元素到最后一个元素的值初始化v4

1.2vector迭代器的使用
iterator的使用接口说明
begin + end(重点)获取第一个数据位置的iterator/const_iterator,获取最后一个数据的下一个位置的iterator/const_iterator
rbegin + rend获取最后一个数据位置的reverse_iterator,获取第一个数据前一个位置的reverse_iterator

微提醒:end()是返回最后一个位置下一个位置的iterator,迭代器的用法类似指针的用法,都是通过解引用来获取元素的值,++,--来控制指针的移动,但是迭代器并不是指针

代码2:
int main()
{
	vector<int> v1(10,2);
	vector<int> v2(++v1.begin(),--v1.end());

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

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

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

运行结果:

 

解析:由于vector底层是一块连续的空间,存储的数据都是有序的,所以我们可以通过下标引用来访问元素的值,所以我们先通过一个for循环来访问v2中的元素,v2.size()中的size()是vector提供的接口之一,我们后续会说,并打印出v2中的每一个元素的值,这和数组的访问方式是类似的;而第二段代码是使用了迭代器,vector<int>代表可以存储整形元素的一个对象,::被用来指定 iterator 是属于 vector<int> 这个类的类型,这意为着iterator是vector<int>类的一个成员,it是一个变量名,它指向v1的开始位置,当it不为v1的最后位置时,它就会像指针一样向后遍历,将指向的位置的值解引用并打印出来,像指针一样向后走一步直到遇到v1的最后位置;而第三个代码又叫做范围for,它的原理和迭代器类似,但是范围for不是每一个容器都可以使用而迭代器则可以

1.3vector空间增长问题
容量空间接口说明
size获取数据个数
capacity获取容量大小
empty判断是否为空
resize(重点)改变vector的size
reserve(重点)改变vector的capacity

  • reserve
    void reserve (size_type n);
    请求容器vector至少可以存储n个元素,如果n大于目前容器的容量大小,那么编译器就会扩容以此来存储元素,如果存在其他情况语法中没有明确规定,怎么处理取决于具体的编译器,而且reserve只负责开辟空间,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问题
  • resize:调整容器的大小,使其包含n个元素,如果n小于当前容器的大小,那么将会缩容使其仅包含n个元素,超出大小的元素将会被移除;如果n大于当前容器的大小,那么将会扩容使其容器大小为n包含n个元素;同时resize在开辟空间的同时还会进行初始化

代码3:
int main()
{
	vector<int> v1(10, 1);
	cout << v1.size() << endl;
	cout << v1.capacity() << endl;
	cout << endl;

	v1.reserve(20);//20 > 容量大小capacity10
	cout << v1.size() << endl;
	cout << v1.capacity() << endl;
	cout << endl;


	v1.reserve(15);//15 < 容量大小capacity20
	cout << v1.size() << endl;
	cout << v1.capacity() << endl;
	cout << endl;

	v1.reserve(5);//5 < 容量大小capacity20
	cout << v1.size() << endl;
	cout << v1.capacity() << endl;

	return 0;
}

解析:首先我们先定义了一个变量v1,然后我们打印出v1的数据个数和容量大小,接着我们给v1reserve20个元素,由于20大于容量的大小,所以v1的容量大小将会扩容至20;接着我们给v1reserve15个元素,由于15小于容量的大小20,所以v1的容量大小的变化取决于具体的编译器,在vs编译器下默认不会做任何变化,所以v1的容量大小没有改变,还是20;接着我们给v1reserve5个元素,由于5小于容量的大小20,所以v1的容量大小的变化取决于具体的编译器,在vs编译器下默认不会做任何变化,所以v1的容量大小没有改变。而v1的size一直都没有改变

代码4:
int main()
{
	vector<int> v1(10,1);
	cout << v1.size() << endl;
	cout << v1.capacity() << endl;
	cout << endl;

	v1.resize(5);//5 < v1的数据个数
	cout << v1.size() << endl;
	cout << v1.capacity() << endl;
	cout << endl;

	v1.resize(15);//15 > v1的数据个数
	cout << v1.size() << endl;
	cout << v1.capacity() << endl;
	cout << endl;

	v1.resize(20);//20 > v1的数据个数
	cout << v1.size() << endl;
	cout << v1.capacity() << endl;
	cout << endl;

	return 0;
}

解析:首先我们先定义了一个变量v1,然后我们打印出v1的数据个数和容量大小,接着我们给v1resize5个元素,由于5小于v1的数据个数10,所以v1将会进行缩容size将会变成5;接着我们给v1resize15个元素,由于15大于v1的数据个数5,所以v1将会进行扩容size将会变成15;接着我们给v1resize20个元素,由于20大于v1的数据个数15,所以v1将会进行扩容size将会变成20,而v1的容量大小也在不断变化着

代码5:
int main()
{
	vector<int> v1(10, 1);

	v1.resize(15,8);//15 > v1的数据个数10,剩余的5个空间会用8来填充

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

解析:当使用resize后数据个数大小大于原有数据个数时将会进行扩容操作,前原有空间10的元素保持不变,新扩的空间5使用指定的元素8填充 

1.4vector增删查改
vector增删查改接口说明
push_back   (重点)尾插
pop_back    (重点)尾删
find查找(注意这个是算法模版的接口,不是vector的成员接口)
insert在position之前插入val
erase删除position位置的数据
swap交换两个vector的数据空间
operator[]    (重点)像数组一样访问
代码:6:
int main()
{
	vector<int> v1(10, 1);
	v1.push_back(2);
	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

	v1.insert(v1.begin() + 3, 5);
	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

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

	return 0;
}

解析:在v1的后面尾插一个2然后使用范围for打印v1中的全部元素,接着使用insert在v1开始位置向后加3的位置插入一个5然后使用范围for打印v1中的全部元素,最后我们使用的是下标的方式像访问数组一样访问v1

2.1vector迭代器失效问题

迭代器的主要作用就是让算法能够不用关心底层数据结构,其底层实际就是一个指针,或者是对指针进行了封装,比如:vector的迭代器就是原生态指针T*。因此迭代器失效,实际上就是迭代器底层对应指针所指向的空间被销毁了,而使用了一块已经被释放的空间,造成的后果是程序崩溃(即如果继续使用已经失效的迭代器,程序可能会崩溃)。

对于vector可能会导致其迭代器失效的操作有:

1.会引起其底层空间改变的操作,都有可能是迭代器失效,比如:resize,reserve,insert,push_back等

代码7:
int main()
{
	vector<int> v1{ 1,2,3,4,5,6 };
	auto it = v1.begin();
	v1.resize(100, 5);

	while (it != v1.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;

	return 0;
}

 

解析:运行时编译器会报错这是因为vector底层是一个连续的空间,当我们使用resize来扩容时,因为需要扩容所以编译器可能重新为v1分配空间,那么这时候就需要移动元素,指向原数据的迭代器就会失效,这时编译器就会报错

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

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

相关文章

Java11环境安装(Windows)

目录 1 Java11安装2 配置2.1 JavaHome配置2.2 CLASSPATH配置PATH路径配置 3 验证 1 Java11安装 从官网下载Java11安装包&#xff1a;jdk-11_windows-x64_bin.exe,安装时选择安装到D:\Java目录。 安装完目录结构如下&#xff1a; 2 配置 2.1 JavaHome配置 如下图所示配置JAV…

Ubuntu构建只读文件系统

本文介绍Ubuntu构建只读文件系统。 嵌入式系统使用过程中&#xff0c;有时会涉及到非法关机&#xff08;比如直接关机&#xff0c;或意外断电&#xff09;&#xff0c;这可能造成文件系统损坏&#xff0c;为了提高系统的可靠性&#xff0c;通常将根文件系统设置为只读&#xf…

Linux下进程间的通信--信号量

前言&#xff1a; 资源竞争&#xff1a; 资源竞争&#xff08;Race Condition&#xff09;是多线程或多进程环境中的一种常见问题&#xff0c;它发生在多个进程或线程并发访问和修改同一资源&#xff08;如内存位置、文件、数据库记录等&#xff09;时&#xff0c;而最终结果…

mysql学习教程,从入门到精通,SQL AND OR 运算符(12)

1、SQL AND & OR 运算符 在本教程中&#xff0c;您将学习如何在子句中使用ASELECT column1_name, column2_name, columnN_nameFROM table_nameWHERE condition1 AND condition2;ND&#xff06;OR运算符&#xff0c;WHERE以根据多个条件过滤记录。 1.1、根据条件选择记录 …

从代码直观理解Self-Attention和Cross-Attention的本质区别

Transformer的模型架构实际上非常简单&#xff0c;Self-Attention 和 Cross-Attention 仅仅是在 k, v上有所不同&#xff08;这里不讨论 mask&#xff09;。 论文原文&#xff1a;Attention Is All You Need 我们可以使用同一个 Attention 类来实现 Self-Attention 和 Cross-At…

day11-多线程

一、线程安全问题 线程安全问题出现的原因&#xff1f;存在多个线程在同时执行同时访问一个共享资源存在修改该共享资源 线程安全:多个线程同时修改同一个资源 取钱案例 小明和小红是一对夫妻&#xff0c;他们有一个共同的账户&#xff0c;余额是10万元 如果小明和小红同时来取…

速看!6款可以写论文的ai写作网站,这才是真正的论文神器!(含教程)

在当今信息爆炸的时代&#xff0c;AI写作工具的出现极大地提高了写作效率和质量。特别是对于需要撰写论文的学生和研究人员来说&#xff0c;这些工具提供了极大的便利。本文将重点介绍一款备受推荐的AI写作平台——千笔-AIPassPaper&#xff0c;并结合相关教程帮助用户更好地使…

【北京迅为】《STM32MP157开发板使用手册》- 第二十四章 STM32CubeIDE的初步使用

iTOP-STM32MP157开发板采用ST推出的双核cortex-A7单核cortex-M4异构处理器&#xff0c;既可用Linux、又可以用于STM32单片机开发。开发板采用核心板底板结构&#xff0c;主频650M、1G内存、8G存储&#xff0c;核心板采用工业级板对板连接器&#xff0c;高可靠&#xff0c;牢固耐…

校园水电费管理微信小程序的设计与实现+ssm(lw+演示+源码+运行)

校园水电费管理小程序 摘 要 随着社会的发展&#xff0c;社会的方方面面都在利用信息化时代的优势。互联网的优势和普及使得各种系统的开发成为必需。 本文以实际运用为开发背景&#xff0c;运用软件工程原理和开发方法&#xff0c;它主要是采用java语言技术和mysql数据库来…

基于SSM的学生信息管理系统(选课管理系统)的设计与实现 (含源码+sql+视频导入教程)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 基于SSM的学生信息管理系统&#xff08;选课管理系统&#xff09;13拥有三种角色 管理员&#xff1a;学生管理、教师管理、专业管理、课程管理、审批管理、课程表管理、开课管理、教室管…

高德地图JS API加载行政区边界AMap.Polygon

&#x1f916; 作者简介&#xff1a;水煮白菜王 &#xff0c;一位资深前端劝退师 &#x1f47b; &#x1f440; 文章专栏&#xff1a; 高德AMap专栏 &#xff0c;记录一下平时在博客写作中&#xff0c;总结出的一些开发技巧✍。 感谢支持&#x1f495;&#x1f495;&#x1f49…

大模型LLM之SpringAI:Web+AI(二)

2.2.2、ChatModel API(聊天模型API) 聊天模型太多了,这里只写OpenAI和Ollama ChatModel和ChatClient区别:ChatClient针对的是所有模型,共用一个客户端。而ChatModel是针对各个模型实现的。 (1)OpenAI 自动配置 <dependency><groupId>org.springframework…

vue3 内置组件 <Suspense>

官方文档&#xff1a; <Suspense> 指南-Suspense 官方提示&#xff1a; <Suspense> 是一项实验性功能。它不一定会最终成为稳定功能&#xff0c;并且在稳定之前相关 API 也可能会发生变化。 <Suspense>是一个内置组件&#xff0c;用来在组件树中协调对异步依…

git删除本地分支报错:error: the branch ‘xxx‘ is not fully merged

git删除本地分支报错&#xff1a;error: the branch xxx is not fully merged error: the branch xxx is not fully merged 直接&#xff1a; git branch -D xxx 就可以。 如果删除远程分支&#xff1a; git push origin --delete origin/xxx git强制删除本地分支 git branc…

如何将Git本地代码推送到Gitee云端仓库

如何将Git本地代码推送到Gitee云端仓库 在使用Git进行版本控制时&#xff0c;将本地代码推送到远程仓库是一个基本且重要的操作。本文将详细介绍如何将你的Git本地代码推送到Gitee&#xff08;码云&#xff09;云端仓库。Gitee是一个国内非常流行的代码托管平台&#xff0c;类…

NX—UI界面生成的文件在VS上的设置

UI界面保存生成的三个文件 打开VS创建项目&#xff0c;删除自动生成的cpp文件&#xff0c;将生成的hpp和cpp文件拷贝到项目的目录下&#xff0c;并且在VS项目中添加现有项目。 修改VS的输出路径&#xff0c;项目右键选择属性&#xff0c;链接器中的常规&#xff0c;文件路径D:…

线性代数 第七讲 二次型_标准型_规范型_坐标变换_合同_正定二次型详细讲解_重难点题型总结

文章目录 1.二次型1.1 二次型、标准型、规范型、正负惯性指数、二次型的秩1.2 坐标变换1.3 合同1.4 正交变换化为标准型 2.二次型的主要定理3.正定二次型与正定矩阵4.重难点题型总结4.1 配方法将二次型化为标准型4.2 正交变换法将二次型化为标准型4.3 规范型确定取值范围问题4.…

《中国制药设备行业市场现状分析与发展前景预测研究报告》

报告导读&#xff1a;本报告从国际制药设备发展、国内制药设备政策环境及发展、研发动态、供需情况、重点生产企业、存在的问题及对策等多方面多角度阐述了制药设备市场的发展&#xff0c;并在此基础上对制药设备的发展前景做出了科学的预测&#xff0c;最后对制药设备投资潜力…

​​操作系统 ---- 进程调度的时机、切换与过程

目录 一、进程调度的时机 1.1 什么时候需要进行进程调度与切换&#xff1f; 1.2 什么情况下不能进行进程调度与切换&#xff1f; 二、进程调度的方式 2.1 非抢占方式(Nonpreemptive Mode) 2.2 抢占方式(Preemptive Mode) 三、总结 一、进程调度的时机 进程调度&am…

FreeRTOS内部机制学习04(任务通知和软件定时器)

文章目录 何为任务通知&#xff1f;任务通知使用例子任务通知的优势以及劣势优势劣势 深入源码看看API函数内部干了什么函数的种类函数都做了啥&#xff1f; 软件定时器软件定时器的作用软件定时器内部到底做了什么实现了“闹钟”功能引入守护任务&#xff0c;守护任务做了啥&a…