C++_STL---vector

vector的相关介绍

  1. vector是表示可变大小数组的序列容器。我们学习的时候就可以把它看作是像数组一样的东西。
  2.  vector采用的连续存储空间来存储元素。也就是意味着我们可以采用下标对vector的元素进行访问,时间复杂度和数组一样高效,为O(1)。但是又不完全像数组,因为它的大小是可以动态改变的,而且它的大小会被容器自动处理。
  3. vector使用动态分配数组来存储它的元素,当新元素插入时,为了增加存储空间,这个数组需要被重新分配大小。
  4. vector分配空间策略:vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存储空间更大。
  5. 与其它动态序列容器相比(deque, list and forward_list),vector在访问元素的时候更加高效,在末尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。

想要了解更多关于vector的详细内容,请点击vector的文档介绍

vector的使用

注意:本章只介绍一些比较常用的接口

vector的相关定义

构造函数声明接口说明代码演示
vector()无参构造vector<int> v1;
vector(size_t n, const T& val = T())构造并初始化n个val

vector<int> v2(5, 10);

//初始化为5个值为10的整数

vector(const vector<T>& v)拷贝构造vector<int> v3(v2);
vector(InputIterator first, InputIterator last)使用迭代器进行初始化构造vector<int> v4(v3.begin(), v3.end());

 vector的空间增长问题

容量空间接口说明
resize改变vector的size
reserve改变vector的capacity

特别说明:

  • capacity的代码在vs和g++下分别运行会发现,vs下capacity是按1.5倍增长的,g++是按2倍增长的。不要固化的认为,vector增容都是2倍,具体增长多少是根据具体的需求定义的。vs是PJ版本STL,g++是SGI版本STL。
  • reserve只负责开辟空间,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问题。
  • resize在开空间的同时还会进行初始化,影响size。

vector的增删查改

vector的增删查改接口说明代码演示
insert(慎用)在pos位置之前插入valiterator insert(iterator pos, const T& val)
erase(慎用)删除pos位置数据iterator erase(iterator pos)
operator[]像数组一样访问T& operator[] (size_t n)

ps. 这些内容我会在下面讲解底层实现的代码,请耐心阅读

vector的迭代器失效问题

迭代器是什么?简单理解迭代器就是像指针一样的东西,我们在使用的时候不用关心其底层的细节,只需像指针一样来使用就可以。而迭代器失效,实际就是迭代器底层对应指针所指向的空间被销毁了,使用一块已经被释放(销毁)的空间,造成的后果是程序崩溃(即如果继续使用已经失效的迭代器,程序可能会崩溃)。

底层空间扩容时,可能会引起迭代器失效

比如:resize、reserve、insert、assign、push_back等,都会引起迭代器失效

例:使用insert往某个位置插入元素时,可能会导致vector扩容,也就是说vector底层原理旧空间被释放掉,而在打印时,it还使用的是释放之前的旧空间,在对it迭代器操作时,实际操作的是一块已经被释放的空间,而引起代码运行时崩溃。解决方法:给it重新赋值即可。

int main()
{
    vector<int> v1{1,2,3,4};
    // find函数:查找某个元素,如果找到了则返回该元素的迭代器,否则返回end()位置的迭代器
    vector<int>::iterator it = find(v1.begin(), v1.end(), 2);
    if (it != v1.end())
    {
        // 在查找的元素前插入200
        // v1.insert(it, 200); 这样写则会导致迭代器失效
    	it = v1.insert(it, 200); //给it重新赋值

    	cout << *it << " ";
    }
    cout << endl;
    return 0;
}

 指定位置元素的删除操作,可能会引起迭代器失效

例:erase的功能是删除pos位置的元素。erase删除pos位置元素后,pos位置之后的元素会往前搬移,没有导致底层空间的改变,理论上讲迭代器不应该会失效,但是:如果pos刚好是最后一个元素,删完之后pos刚好是end的位置,而end位置是没有元素的,那么pos就失效了。因此删除vector中任意位置上元素时,vs就认为该位置迭代器失效了。

int main()
{
    vector<int> v1{1,2,3,4};
    vector<int>::iterator it = v1.begin();
    while (it != v1.end())
    {
    	if (*it % 2 == 0)
            //给it重新赋值,解决迭代器失效的问题
		    it = v1.erase(it); 
    	else
		    ++it;
    }
    return 0;
}

 注意:无论上面说的那种迭代器失效,都是针对vs所说;对于g++结果是不相同的

vector部分接口函数的底层实现

vector的初始化函数

//使用迭代器进行初始化构造
template <class InputIterator>
vector(InputIterator first, InputIterator last)
{
	while (first != last)
	{
		push_back(*first);
		++first;
	}
}
//n个val构造
vector(size_t n, const T& val = T())
{
	reserve(n); //提前开好空间,减小消耗
	for (size_t i = 0; i < n; i++)
	{
		push_back(val);
	}
}
//拷贝构造
vector(const vector<T>& v)
{
	reserve(v.capacity());
	for (const auto& e : v)
	{
		push_back(e);
	}
}

 vector的插入、删除函数

iterator insert(iterator pos, const T& val)
{
	assert(pos >= _start);
	assert(pos <= _finish);

	if (_finish == _end_of_storage)
	{
		size_t len = pos - _start; //记录pos的位置
		size_t newcapacity = capacity() == 0 ? 4 : 2 * capacity();
		reserve(newcapacity);

		pos = _start + len;        //更新新空间pos的位置 (迭代器失效的根本原因)
	}

	iterator end = _finish;
	while (end >= pos)             //从后往前依次挪动元素
	{
		*(end + 1) = *end;
		--end;
	}
	*pos = val;
	++_finish;

	return pos;                    
}
iterator erase(iterator pos)
{
	assert(pos >= _start);
	assert(pos < _finish);

	iterator begin = pos;
	while (begin < _finish - 1)  //从前往后挪动元素
	{
		*(begin) = *(begin + 1);
		++begin;
	}
	--_finish;

	return pos;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何找合适的C++项目给自己的简历加分?

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「嵌入式的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01; C的工作多种多样&#x…

[深度学习] 前馈神经网络

前馈神经网络&#xff08;Feedforward Neural Network, FFNN&#xff09;是人工神经网络中最基本的类型&#xff0c;也是许多复杂神经网络的基础。它包括一个输入层、一个或多个隐藏层和一个输出层。以下是详细介绍&#xff1a; 1. 结构 1. 输入层&#xff08;Input Layer&am…

入门网络安全工程师要学习哪些内容

大家都知道网络安全行业很火&#xff0c;这个行业因为国家政策趋势正在大力发展&#xff0c;大有可为!但很多人对网络安全工程师还是不了解&#xff0c;不知道网络安全工程师需要学什么?知了堂小编总结出以下要点。 网络安全工程师是一个概称&#xff0c;学习的东西很多&…

Flexsim物流仿真入门-利用网络节点控制行走路线

在布局优化过程中&#xff0c;往往叉车&#xff0c;操作人员的搬运&#xff0c;是会按照一定的行走路线进行的&#xff0c;这就需要我们进行节点的设计&#xff0c;以此来实现特定路径的行走。 在构建过程中&#xff0c;这里将会以案例的形式进行讲解说明。 1&#xff09;构建…

【Linux】进程间通信_3

文章目录 七、进程间通信1. 进程间通信分类命名管道 未完待续 七、进程间通信 1. 进程间通信分类 命名管道 管道应用的一个限制就是只能在具有共同祖先&#xff08;具有亲缘关系&#xff09;的进程间通信。如果我们想在不相关的进程之间交换数据&#xff0c;可以使用FIFO文件…

操作系统之《死锁与银行家算法》【知识点+详细解题过程】

知识点&#xff1a; 1、什么是死锁&#xff1f;&#xff08;别名"三角恋"&#xff0c;我喜欢你你喜欢他他喜欢我&#xff0c;明明都单身但是就是‘占有’不了&#xff09; 一组进程中&#xff0c;每个进程都无限等待被该组进程中另一进程所占有的资源,因而永远无法…

vue-cli的搭建过程

一、创建一个vue2的项目 二、创建成功后删除这三个文件 三、新建一个App.vue文件 四、在文件中添加这一段话 五、打开命令框输入指令下载router路由 六、新建一个router目录&#xff0c;新建index.js文件 七、导入你的路由&#xff0c;进行配置 打开命令行工具&#xff0c;进入…

【Python Tips】创建自己的函数包并安装进Anaconda,像引入标准包一样直接import导入

目录 一、引言 二、方法步骤 步骤一&#xff1a;创建包目录结构 步骤二&#xff1a;配置__init__.py文件 步骤三&#xff1a;文件夹外配置setup.py文件 步骤四&#xff1a;终端Pip安装 三、结尾 一、引言 在编写项目代码的时候&#xff0c;有些自定义功能的函数是可以复用的。…

Java面向对象特性

Java继承&#xff1a; 继承的概念&#xff1a; 在Java中&#xff0c;继承&#xff08;inheritance&#xff09;是面向对象编程的一个重要概念&#xff0c;它允许一个类&#xff08;子类&#xff09;继承另一个类&#xff08;父类&#xff09;的属性和方法。通过继承&#xff0c…

MySQL高级-SQL优化- order by 优化(尽量使用覆盖索引、注意联合索引创建的规则、增大排序缓冲区大小)

文章目录 0、order by优化原则1、Using filesort2、Using index3、连接数据库4、查看索引5、删除索引6、按照年龄进行排序7、执行计划 order by age8、执行计划 order by age,phone9、创建联合索引 (age,phone)10、再次执行计划 order by age11、再次执行计划 order by age,pho…

SpringMVC处理器映射器HandlerMapping详解

目录 一、前言 二、initHandlerMappings 三、处理器映射器架构 策略接口 请求链 模版类 四、RequestMappingHandlerMapping的初始化 HandlerMethod映射器模版类的初始化 AbstractHandlerMethodMapping.MappingRegistry&#xff1a;内部类注册中心 五、Reques…

从菌群代谢到健康影响——认识肠道丙酸和丁酸

谷禾健康 短链脂肪酸这一词经常出现在谷禾的文章和报告中&#xff0c;那你真的了解短链脂肪酸吗&#xff1f;短链脂肪酸(SCFA)主要是肠道微生物群在结肠内通过发酵碳水化合物(包括膳食和内源性碳水化合物&#xff0c;主要是抗性淀粉和膳食纤维)和一些微生物可利用的蛋白质而产生…

一个人 三个月 干了二十万

相信很多人是被这个标题吸引进来的&#xff0c;但我并不是标题党&#xff0c;我也很讨厌标题党&#xff0c;这篇文章也不在乎流量&#xff0c;更多的是想记录下。 出来创业三个多月了&#xff0c;给大家汇报一下这段时间的业绩吧。一个人&#xff0c;三个多月&#xff0c;干了…

线性图标绘制指南:从基础到精通

图标在生活中随处可见。相比文字来说&#xff0c;图标可以让人在更短的时间内认知并了解信息&#xff0c;并且大大提升信息的视觉美观性&#xff0c;增加设计的艺术感染力。在用户界面中使用图标&#xff0c;是一种用户熟知的设计模式。而线性图标是通过提炼图形轮廓&#xff0…

TIOBE 6月榜单出炉!编程语言地位大洗牌,谁才是王?

C历史上首次超越C&#xff01;&#xff01;&#xff01; TIOBE 公布了 2024 年 6 月编程语言的排行榜&#xff1a;https://www.tiobe.com/tiobe-index/ 排行榜 以下列出的语言代表了第51至第100名。由于它们之间的差异相对较小&#xff0c;编程语言仅以字母顺序列出。 ABC, A…

ubuntu16.04上搭建qt开发环境

安装qt 下载qt在linux下的安装包qt-opensource-linux-x64-5.8.0.run&#xff1b;将安装包拷贝到ubuntu16.04上&#xff1b;执行如下命令进行安装&#xff0c;注意&#xff1a;安装前先断开虚拟机的网络&#xff0c;这样就避免了注册账户的操作 基本上一路按“next”键&#xf…

使用青否数字人直播软件有哪些优势?

使用青否数字人主播主要具有以下优势&#xff1a; 1、降低直播门槛 在垂直程度较高、专业度更强的行业&#xff0c;面对相关品牌们“专业主播难培养”的问题。数字人主播的学习技能和灵活优势尽显。通过数字人直播可以借助知识库配置与AI能力&#xff0c;快速获得技术性知识&am…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 螺旋矩阵填数(100分) - 三语言AC题解(Python/Java/Cpp)

&#x1f36d; 大家好这里是清隆学长 &#xff0c;一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 &#x1f4bb; ACM银牌&#x1f948;| 多次AK大厂笔试 &#xff5c; 编程一对一辅导 &#x1f44f; 感谢大家的订阅➕ 和 喜欢&#x1f497; &#x1f…

c语言--指针

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文整理c语言中指针的相关知识点。 指针概念 指针存储的就是数据的地址。 直观理解: 李华家是北洋路130号1单元101 用变量处理数据: 我们去李华家拿数据。 用指针处理数据: 我们去北洋路130号1单元101拿数据…

石墨舟氮气柜的特点和使用要求介绍

石墨舟是一种在半导体、太阳能光伏等高科技产业中广泛使用的专用工具&#xff0c;主要由高纯度石墨材料制成。它的形状通常像一只船&#xff0c;因此得名“石墨舟”。石墨舟主要用于承载硅片或其他基板材料通过各种高温处理过程&#xff0c;是制造半导体器件和太阳能电池片的关…