【C++】vector的使用

news2024/12/23 13:45:33

文章目录

  • 1. 主要结构
  • 2. 构造函数与复制重载
  • 3. 迭代器
  • 4. 容量相关
    • 1.容量读取
    • 2.容量修改
  • 5. 数据访问
  • 6. 数据修改
    • 1. 尾插尾删
    • 2.任意位置的插入删除
  • 7.其他接口

在之前我们学习了string的使用与模拟实现,在参考文档中可以发现,vector和string以及其他的容器的接口基本都相同,所以这里也就简要的介绍一下。

同样的,在这里还是要说一下,对于STL库的学习,不可能在一朝一夕之间学完,要学会去查看文档和多练习vector参考文档

1. 主要结构

image-20230418154326704

vector没有像string一样进行类型重定义typedef basic_string<char> string,所以在使用vector的时候要指定模板参数类型例如vector<int>

2. 构造函数与复制重载

image-20230418160501765

可以看到vector的构造函数实现相较于string就简化了很多,一共分为四个,分别是默认构造,指定长度和值的构造,迭代器区间构造,拷贝构造

void Test_Construct()
{
	vector<int> v1;//默认构造
	vector<int> v2(10, 3);//指定长度和值的构造
	string s("aaaaaaaaaaaaaa");
	vector<char> v3(s.begin(), s.end());//迭代器区间构造
	vector<char> v4(v3);//拷贝构造
}

image-20230418213255290

通过监视查看四个对象的值如上。

3. 迭代器

由于vector也是通过动态数组实现的,所以原生指针就能很好的支持迭代器行为,所以在vector中的迭代器本质也是指针。

image-20230419080950623

可以看到和string一样,vector的迭代器也分为普通迭代器,反向迭代器,const迭代器,const反向迭代器。

image-20230419081331230

对于迭代器和反向迭代器的工作方式如上图。

4. 容量相关

1.容量读取

1. size

image-20230419081458467

返回一个size_t类型的vector中数据个数

2. capacity

image-20230419081623104

返回一个size_t类型的vector的容量。

使用范例:

void Test_Capacity()
{
	vector<int> v;
	v.reserve(10);
	for (size_t i = 0; i < 5; ++i)
	{
		v.push_back(i);
	}
	cout << "size:" << v.size() << endl;
	cout << "capacity:" << v.capacity() << endl;
}

运行结果为:

image-20230419082018970

2.容量修改

1. reserve

image-20230419082143747

扩大vector的容量到n,如果原来vector的容量大于等于n,不做任何操作

void Test_Capacity2()
{
	vector<int> v(5, 1);
	cout << "before reserve capacity:" << v.capacity() << endl;
	v.reserve(10);
	cout << "after reserve capacity:" << v.capacity() << endl;
}

image-20230419082505632

2. resize

image-20230419082619237

修改vector中的数据个数,如果n小于size,那就修改size;如果n大于size但是小于capacity,那就尾插数据直到size==n,如果n大于capacity,那就先扩容到n,再填充数据。

void Test_Capacity3()
{
	vector<int> v(5, 1);
	cout << "before resize capacity:" << v.size() << endl;
	v.resize(10);
	cout << "after resize capacity:" << v.size() << endl;
	for (auto e : v)
	{
		cout << e << " ";
	}
	cout << endl;
}

image-20230419083020574

5. 数据访问

与string类似,在数据访问中也有很多接口,但是最常用的还是[]的重载,其余基本不常用,这里我们就不过多赘述

image-20230419083205192

[]实际上是一个运算符重载,使vector也具有类似下标访问的能力,返回值是vector中存放元素类型的引用

对于[]的重载,在库里面支持了两种重载,分别是普通类型的和const类型的用于支持多样化的使用环境

怎么判断需要实现const或者非const版本?

  1. 对于只读接口,只实现const版本即可
  2. 对于只写接口,只实现非const版本即可
  3. 对于可读可写的接口,需要同时实现const版本和非const版本
void Test_Access()
{
	vector<int> v(10);
	for (size_t i = 0; i < v.size(); ++i)
	{
		v[i] = i;
	}
	for (size_t i = 0; i < v.size(); ++i)
	{
		cout << v[i] << " ";
	}
	cout << endl;
}

image-20230419083716301

6. 数据修改

1. 尾插尾删

1. push_back

image-20230419085534437

尾插数据,插入前会进行扩容操作,每次扩容的大小取决于编译器的实现

2. pop_back

image-20230419085728462

如果vector中有数据的话,尾删一个数据,否则会由assert中断程序或者抛出异常,具体情况取决于编译器的实现

void Test_Modifity()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	v.pop_back();
	v.pop_back();
	v.pop_back();
	v.pop_back();
	v.pop_back();
	v.pop_back();
}

image-20230419090506991

2.任意位置的插入删除

1. insert

image-20230419090827948

在传入的任意位置插入一个数据或者迭代器区间的数据

2. erase

image-20230419091215741

删除任意位置的值或者任意一个迭代器区间的值

void Test_Modifity2()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	v.insert(v.begin() + 3, 30);
	v.erase(v.begin());
    for (auto e : v)
	{
		cout << e << " ";
	}
	cout << endl;
}

image-20230419092501957

这里注意一下,vector中会出现迭代器失效的问题

❗❗==vector中的迭代器失效问题==❗❗

第一个问题:迭代器的出现原因是什么?

迭代器的设计模式,为了不暴露底层实现细节,提供统一的方式来访问容器,对于vector,其迭代器本质上就是原生指针T*,所以对vector来说,迭代器失效的原因就是原迭代器指向的空间被销毁,导致出现野指针。

第二个问题:导致迭代器失效的操作有哪些?

✅迭代器失效的原理是底层空间改变,导致产生野指针,所以所有的底层空间的改变都有可能使迭代器失效,例如:reserve,resize,push_back,insert等。

✅除了对底层空间的改变之外,erase也会导致迭代器失效。

第三个问题:按照我们上一个问题的逻辑,erase没有使底层空间发生改变啊,为什么也会使迭代器失效?

✅虽然erase没有改变底层空间,但是,如果erase删除的是vector中最后一个元素,刚好删除完之后pos位置是end指向的位置,那么迭代器就失效了。

✅就算删除的不是最后一个元素,那么迭代器指向的位置的值也是改变了的,严格意义上来说,也是不能实现我们所需要的功能的,所以也可以认为是迭代器失效了。

第四个问题:只有vector会遇到迭代器失效的的情况吗,string有没有迭代器失效的情况?

✅不只是vector有,string和其他的容器都有迭代器失效的情况。

第五个问题:迭代器失效的问题怎么解决呢?

✅在上文中,我们讲解了vector的主要接口,可以注意到,能够引起迭代器失效的接口函数的返回值都是迭代器,这里返回的迭代器就是我们所需要的有效的迭代器。所以,在使用前对迭代器进行重新赋值即可解决

//关于迭代器失效解决的例题:
//对于使用vector存储的数组{0,1,2,3,4,5,6,7,8,9},删除其中所有的偶数元素
int main()
{
	vector<int> v(10);
	for (size_t i = 0; i < 10; ++i)
	{
		v[i] = i;
	}
	vector<int>::iterator it = v.begin();
	while (it != v.end())
	{
		if (*it % 2 == 0)
		{
			it = v.erase(it);
		}
		else
		{
			++it;
		}
	}
	for (auto e : v)
	{
		cout << e << " ";
	}
	cout << endl;
	return 0;
}

7.其他接口

1. clear

image-20230419092648474

删除vector内部所有数据(本质上做的操作就是将vector的size置为0)

2. swap

image-20230419092900368

vector内部实现的一个交换函数,提升效率。

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

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

相关文章

I/O 设备

CPU有两种方法访问IO设备 都是基于PMIO的&#xff0c;Port Mapped I/O 给IO总线上的寄存器编号&#xff0c;CPU向IO总线请求写入或读取数据 &#xff08;x86&#xff09;给特定的内存地址对应上目标IO设备&#xff0c;当CPU读取这段内存的时候&#xff0c;就会把访问转发给IO…

微服务 - Consul服务注册中心

概述 上篇说到构建良好的架构&#xff0c;依托于基础设施建设(自动化测试、自动化部署、服务监控&#xff0c;服务发现、配置中心等等)&#xff0c;决定成败的往往是基础设施建设&#xff0c;所以从搭建一个注册中心和配置中心开始我们新一阶段的启程。 注册中心 注册中心选型…

Cordic算法原理详解

目录 坐标旋转分析 Cordic算法原理 应用举例1&#xff1a;求sin值与cos值 应用举例2&#xff1a;求反正切值 cosθ的还原补偿 坐标旋转数字计算机CORDIC(COordinate Rotation DIgital Computer)算法&#xff0c;通过移位和加减运算&#xff0c;能递归计算常用函数值&#…

《Netty》从零开始学netty源码(四十一)之PoolChunk.runsAvail

runsAvail runsAvail用于记录long型的指针值&#xff0c;是一个LongPriorityQueue数组&#xff0c;LongPriorityQueue的结构如下&#xff1a; array数组用于存储handle的值&#xff0c;其中下标对应SizeClasses中pageIdx&#xff0c;size为array数组的大小&#xff0c;size的大…

1.13|1.14|1.15|1.6、GDB调试

1.13|1.14|1.15|1.6、GDB调试 1.13、GDB调试&#xff08;1&#xff09;&#xff0c;GDB调试&#xff08;2&#xff09;1. 什么是GDB2. 准备工作3. GDB命令—启动、推出、查看代码实际操作①用list查看代码 1.15、GDB调试&#xff08;3&#xff09;1. GDB命令—断点操作实际操作…

Redis 快速上手 Java 增删改查(包含 RedisTemplateConfig 的编写)

一&#xff1a;Redis 数据类型 先了解 redis 的五种基本数据类型。 String 字符串类型&#xff1a;name: "value1"List 列表&#xff1a;names: ["value1", "value2", "value2"]Set 集合&#xff1a;names: ["value1", &qu…

多源迁移学习网络补充知识用于具有不可见故障的机器智能诊断

**摘要&#xff1a;**当前基于深度迁移学习的故障诊断的大多数成功需要两个假设&#xff1a;1&#xff09;源机器的健康状态集合应当与目标机器的健康状态集合重叠;2&#xff09;目标机器样本的数量跨健康状态平衡。然而&#xff0c;这样的假设在工程场景中是不现实的&#xff…

【闲聊杂谈】HTTPS原理详解

HTTPS和HTTP的区别 HTTP虽然使用极为广泛, 但是却存在不小的安全缺陷, 主要是其数据的明文传送和消息完整性检测的缺乏, 而这两点恰好是网络支付, 网络交易等新兴应用中安全方面最需要关注的。 关于 HTTP的明文数据传输, 攻击者最常用的攻击手法就是网络嗅探, 试图从传输过程…

Redis高可用高性能缓存的应用系列06 - 热Key,大Key,并发竞争解决方案

概述 终于迎来了Redis系列的尾声&#xff0c;本文针对Redis常遇到的热Key&#xff0c;大Key&#xff0c;并发竞争解决方案进行介绍。 热Key 什么是热key?当一个key的访问量明显大于其他key的时候&#xff0c;他就可以被称为热key。 热Key带来的问题 热key占用大量的CPU资…

黑马在线教育数仓实战7

1. hive的相关的优化 1.1 hive的相关的函数(补充说明) if函数: 作用: 用于进行逻辑判断操作语法: if(条件, true返回信息,false返回信息) 注意: if函数支持嵌套使用 nvl函数: 作用: null值替换函数格式: nvl(T value, T default_value) COALESCE函数 作用: 非空查找函数:格式…

Windows安装GPU环境CUDA、深度学习框架Tensorflow和Pytorch

Windows安装GPU环境CUDA、深度学习框架Tensorflow和Pytorch 1、未安装CUDA使用tensorflow报错 import tensorflow as tf2022-03-06 15:14:38.869955: W tensorflow/stream_executor/platform/default/dso_loader.cc:60] Could not load dynamic library cudart64_110.dll; dl…

Django | 一文完美解决admin增加新用户只有用户名密码和确认密码的问题

文章目录 如图所示&#xff0c;下面给出解决方案&#xff1a; 如果您使用 使用 Django 默认的后台管理界面添加用户时&#xff0c;只看到了三个字段&#xff08;通常是 username、password和 repassword&#xff09;&#xff0c;那么可以通过定义 add_fieldsets 属性来增加更多…

【JUC】原子操作类

【JUC】原子操作类 文章目录 【JUC】原子操作类1. 原子操作类1.1 基本类型原子类1.2 数组类型原子类1.3 引用类型原子类1.3.1 AtomicReference1.3.2 AtomicStampedReference1.3.3 AtomicMarkableReference 1.4 对象的属性修改原子类 1. 原子操作类 原子操作类如下所示&#xf…

【Linux】进程间通信 --- 管道 共享内存 消息队列 信号量

等明年国庆去西藏洗涤灵魂&#xff0c;laozi不伺候这无聊的生活了 文章目录 一、进程间通信1.什么是通信&#xff1f;&#xff08;IPC&#xff09;2.为什么要有通信&#xff1f;&#xff08;多进程协同&#xff09;3.如何进行通信&#xff1f; 二、基于文件系统的管道通信1.通信…

acwing17给了一个头节点,从尾到头输出链表的元素,顺便练练容器

方法一 建立一个数组&#xff0c;从头到尾遍历一遍链表&#xff0c;然后将链表的每个元素的值赋给数组 犯了一个错误 新建的vector容器是一个可变长的数组&#xff0c;要想像数组下标那样访问前提是这个下标所指向的元素得存在&#xff0c;这也就跟那个声明一维数组得写出长度来…

rk3568 适配摄像头 (CIF协议)

rk3568 适配摄像头 (CIF协议) 在RK3568处理器中&#xff0c;支持CIF协议的摄像头可以通过CSI接口连接到处理器&#xff0c;实现视频数据的采集和处理。同时&#xff0c;RK3568还支持多种图像处理算法和编解码器&#xff0c;可以对采集到的视频数据进行实时处理和压缩&#xff…

[Golang实战] 带你入手gin框架使用,以项目为例

&#x1f61a;一个不甘平凡的普通人&#xff0c;致力于为Golang社区和算法学习做出贡献&#xff0c;期待您的关注和认可&#xff0c;陪您一起学习打卡&#xff01;&#xff01;&#xff01;&#x1f618;&#x1f618;&#x1f618; &#x1f917;专栏&#xff1a;算法学习 &am…

Dear ImGui结合CMake实现基于GLFW和OpenGL3的入门级hello world代码

Dear ImGui结合CMake实现基于GLFW和OpenGL3的入门级hello world代码 如需转载请标明出处&#xff1a;https://blog.csdn.net/itas109 技术交流&#xff1a;129518033 环境&#xff1a; OS: windows 10 / Ubuntu 22.04 imgui: 1.89.5 glw: 3.3.8前言 Dear ImGui 是一个 用于…

alibaba arthas的新人上手教程

背景 Arthas 是Alibaba开源的Java诊断工具。 github开源地址&#xff1a;GitHub - alibaba/arthas: Alibaba Java Diagnostic Tool Arthas/Alibaba Java诊断利器Arthas 上手教程 1.下载arthas&#xff0c;并测试运行demo curl -O https://arthas.aliyun.com/arthas-boot.j…

高防IP的定义与作用

随着网络技术的发展&#xff0c;网络攻击的频率和威力不断升级&#xff0c;对企业和个人的网络安全造成了巨大风险。于是&#xff0c;高防IP作为一种网络安全防护工具应运而生&#xff0c;成为广大用户保障网络安全的重要手段。接下来让我们一起来详细了解下高防IP的定义和作用…