前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >vector常用操作

vector常用操作

作者头像
无敌清风蓝
发布2024-06-04 19:52:50
850
发布2024-06-04 19:52:50
举报
文章被收录于专栏:无敌清风蓝

1.前言

昨晚在家,心血来潮想了解下vector,所以翻cppreference看了看,今天便小小总结下

2.常用函数的思维导图

这是我把cppreference中我常用的摘录下来做成的思维导图,更清晰一点

微信截图_20240305160254.png
微信截图_20240305160254.png

2.1迭代器

迭代器是什么? 简单理解:提供遍历访问的一种方式 官方理解:是一个对象,可以循环访问C++标准库容器中的元素,并提供对各个元素的访问

cbegin的c代表的是返回const,所以他不能修改数据 rbegin的r代表反向第一个

代码语言:javascript
复制
int main()
{
	std::vector<int> v = { 0,1,2,3,4,5 };
	for (auto it = v.begin(); it < v.end(); it++)
	{
		std::cout << *it << " ";
	}
	std::cout << std::endl;
	for (auto it = v.rbegin(); it < v.rend(); it++)
	{
		std::cout << *it << " ";
	}
	std::cout << std::endl;
	for (auto it = v.cbegin(); it < v.cend(); it++)
	{
		std::cout << *it << " ";
		// *it = 1;  错误
	}
	std::cout << std::endl;
	for (auto it = v.crbegin(); it < v.crend(); it++)
	{
		std::cout << *it << " ";
		// *it = 1;  错误
	}
}

输出

代码语言:javascript
复制
0 1 2 3 4 5
5 4 3 2 1 0
0 1 2 3 4 5
5 4 3 2 1 0

2.2容量

size:现在容器中有多少个元素

resize:当新分的内存比现在内存大时,后面新扩充的内存部分,都会用默认元素来填充,所以capacity(内存)也变大;没现在内存大时,原来内存中的元素多的元素会被删除,但是capacity不变

capacity:你分配了多少的内存,即使你里面元素减少了,但是内存也不会减少

shrink_to_fit:把多余的内存给删掉,比如元素4个,内存有5,则把多余的一个内存给干掉,注意这个函数没有返回值

reserve:是内存预留空间,但是没有给新开的内存初始化,只是说明可以利用它,但是不能有效访问空间,因为现在里面什么都没,所以元素个数其实没变。如果预留空间大于当前capacity空间则会重新分配内存 reserve:并不会删除或者添加元素,也不会改变元素的数量 reserve:这个函数设计的是只能用来增加capacity,不能用来减少capacity,传入的参数小于或等于当前的capacity,reserve函数不会做任何事情,所以capacity保持不变

v[5]:这样通过索引的只能访问已存在的元素,否则就访问越界

代码语言:javascript
复制
	std::vector<int> v;
	std::cout << "size:" << v.size() << std::endl;
	// 0
	
	v = { 1,2,3,4,5 };
	std::cout << "size:" << v.size() << std::endl;
	// 5

	v = { 1,2,3,4 };
	std::cout << "size:" << v.size() << std::endl;
	// 4 元素为4个

	std::cout << "capacity:" << v.capacity() << std::endl;
	// 5 内存为5个空间大小

	v.shrink_to_fit();
	std::cout << "capacity:" << v.capacity() << std::endl;
	// 4

	v.resize(10);
	std::cout << "capacity:" << v.capacity() << std::endl;
	// 10
	std::cout << "v[5]:" << v[5] << std::endl;
	// 0 因为resize新增空间时,用默认数据来填充新增加的空间

	for (auto it = v.begin(); it < v.end(); it++)
	{
		std::cout << *it << " ";
	}
	std::cout << std::endl;
	// 1 2 3 4 0 0 0 0 0 0

	v.resize(3);
	for (auto it = v.begin(); it < v.end(); it++)
	{
		std::cout << *it << " ";
	}
	std::cout << std::endl;
	// 1 2 3

	std::cout << "capacity:" << v.capacity() << std::endl;
	// 10

	v.shrink_to_fit();
	std::cout << "capacity:" << v.capacity() << std::endl;
	// 3

	v.reserve(9);
	for (auto it = v.begin(); it < v.end(); it++)
	{
		std::cout << *it << " ";
	}
	std::cout << std::endl;
	// 1 2 3 
	std::cout << "capacity:" << v.capacity() << std::endl;
	// 9
	std::cout << "v[5]:" << v[5] << std::endl;
	// 6619252 随机地址,因为reserve分配的空间还没有初始化,但是resize分配的时候也就初始化了,所以上面的v[5]是0
	// 但其实这样访问是错误的v[5]这是通过[]操作符索引来访问的,但是索引访问只能访问已存在的元素,而此时已存在的元素只有1 2 3
	// 这就是访问越界,因为v里面只有3个元素,5超过了有效范围

	v.reserve(2);
	for (auto it = v.begin(); it < v.end(); it++)
	{
		std::cout << *it << " ";
	}
	std::cout << std::endl;
	// 1 2 3
	std::cout << "capacity:" << v.capacity() << std::endl;
	// 9 因为reserve(2) 2小于9,所以什么都不做

2.3元素访问

代码语言:javascript
复制
		std::vector<int> v = { 0,1,2,3,4,5,6 };

		v.resize(3);
		std::cout << "capacity:" << v.capacity() << std::endl;
		// 7
	
		for (auto it = v.begin(); it < v.end(); it++)
		{
			std::cout << *it << " ";
		}
		std::cout << std::endl;
		// 0 1 2

		std::cout << "v[6]:" << v[6] << std::endl;
		// 6

		//std::cout << v.at(3) << std::endl;
		// 代码会报错,因为at里面会检查是否访问的超过了size,也就是有效元素的范围
		// 而operator[]则没有这个检查

		std::cout << "v.at(2):" << v.at(2) << std::endl;
		// 2

		std::cout << "v.front():" << v.front() << std::endl;
		// 0

		std::cout << "v.back():" << v.back() << std::endl;
		// 2

resize(3)执行后,应该元素里面就剩下0,1,2了,为什么v[6]还能访问呢

这和resize和迭代器工作方式有关,当调用v.resize(3);后,v的大小(size)变为3,但是capacity可能仍然保持不变。这意味着,虽然你删除了一些元素,但是这些元素占用的内存并没有被释放。因此,当你访问v[6]时,你可能仍然能够看到原来的值,因为那块内存尚未被覆盖。然而,这是非常危险的,因为这是未定义的行为。

另一方面,当你使用迭代器遍历v时,迭代器只会访问v的有效元素,也就是说,只会访问v的大小(size)范围内的元素。因此,当你执行for (auto it = v.begin(); it < v.end(); it++)时,你只会看到v的前三个元素,即0,1,2,而不会看到6,因为6已经不再v的大小范围内了。

所以,[]操作符和*it都是读取内存的值,但是他们访问的范围是不同的。[]操作符可以访问到任何位置的内存,包括超出v的大小范围的内存,而*it只能访问到v的大小范围内的内存。

2.4修改数据

assign会清除容器里以前的内容,当输入的元素比原来的容量空间小时,则原来容量空间不变 emplace替代insert emplace_back替代push_back

代码语言:javascript
复制
		std::vector<int> v = { 0,1,2,3,4,5,6 };

		v.resize(3);
		std::cout << "capacity:" << v.capacity() << std::endl;
		// 7
	
		for (auto it = v.begin(); it < v.end(); it++)
		{
			std::cout << *it << " ";
		}
		std::cout << std::endl;
		// 0 1 2

		std::cout << "v[6]:" << v[6] << std::endl;
		// 6

		//std::cout << v.at(3) << std::endl;
		// 代码会报错,因为at里面会检查是否访问的超过了size,也就是有效元素的范围
		// 而operator[]则没有这个检查

		std::cout << "v.at(2):" << v.at(2) << std::endl;
		// 2

		std::cout << "v.front():" << v.front() << std::endl;
		// 0

		std::cout << "v.back():" << v.back() << std::endl;
		// 2

3.迭代器失效的情况

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024/03/05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.前言
  • 2.常用函数的思维导图
    • 2.1迭代器
      • 2.2容量
        • 2.3元素访问
          • 2.4修改数据
          • 3.迭代器失效的情况
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档