STL的vector::resize() 和 vector::reserve()区别和作用详解

2023-11-01 21:40

本文主要是介绍STL的vector::resize() 和 vector::reserve()区别和作用详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、概述

现在数组基本都用vector了,很方便,但可能对vector的某些属性还不是很了解。以前只是大概知道reserve和resize是分别干什么的,但是并不了解它们的真正目的是什么,今天仔细回顾了一下,终于弄懂了,现在做个记录。

二、区别和作用

1. resize() 设置有效空间,reserve() 设置总体容量

通俗点说,假如蔡徐坤要开演唱会,地点定在了A体育馆,这个体育馆可容纳 5000 5000 5000人。在演唱会开始前卖票,发现销量不是很好,只卖出去了大概 300 300 300张票,但为了保险起见(避免溢出),在体育馆内放置了500把椅子。从这个例子来看,体育馆的 5000 5000 5000人容量是一开始蔡徐坤用 r e s e r v e ( ) reserve() reserve() 申请的 5000 5000 5000人总容量,放置的 500 500 500把椅子,是他用 r e s i z e ( ) resize() resize() 申请的 500 500 500人有效空间。

这里的 5000 5000 5000对应着 v e c t o r : : c a p a c i t y ( ) vector::capacity() vector::capacity(),而 500 500 500对应着 v e c t o r : : s i z e ( ) vector::size() vector::size()

用代码来看看是不是这样

#include <iostream>
#include <vector>
using namespace std;int main()
{vector<int> concert;concert.reserve(5000);concert.resize(500);cout << "capacity: " << concert.capacity() << endl;cout << "size: " << concert.size() << endl;
}

在这里插入图片描述
后来,蔡徐坤换到了一个大气球里面开演唱会,这个打气球可以尽可能大的膨胀。蔡徐坤一开始只 r e s e r v e ( ) reserve() reserve() 500 500 500人的容量, r e s i z e ( ) resize() resize() 300 300 300个座位,但是发现大家很喜欢这个气球,进来了更多的人,最后一共进来了 800 800 800人,于是他又 r e s i z e ( ) resize() resize() 800 800 800个座位(增加了300个座位),而这个气球(其实已经不是同一个气球了,已经换成了一个更大的气球)也膨胀到了可以容纳下 800 800 800个人。

看看代码

#include <iostream>
#include <vector>
using namespace std;int main()
{vector<int> concert;concert.reserve(500);concert.resize(300);cout << "capacity: " << concert.capacity() << endl;cout << "size: " << concert.size() << endl;concert.resize(800);cout << endl;cout << "capacity: " << concert.capacity() << endl;cout << "size: " << concert.size() << endl;
}

在这里插入图片描述
可以发现,resize() 调整大小小于 capacity 时,是不会改变 capacity 的,如果大于 capacity 时,则 capacity 也会一起增大。reserve() 的容量大于 capacity 时,也不会改变 size 的,但是如果 reserve 容量小于 resize 呢,答案是也不会改变 size。

#include <iostream>
#include <vector>
using namespace std;int main()
{vector<int> concert;concert.resize(3000);concert.reserve(300);cout << "capacity: " << concert.capacity() << endl;cout << "size: " << concert.size() << endl;
}

在这里插入图片描述

2. vector扩容机制导致迭代器失效

后来,周杰伦也来到了A体育馆开演唱会,因为是暴雨天,以为来的人很好,所以一开始就 r e s i z e ( ) resize() resize() 5000 5000 5000个座位,但是最后却来了 100000 100000 100000名观众,A体育馆容不下这么多人了怎么办,只能大家一起决定搬到另一个可以容纳 100000 100000 100000人的B体育馆。但是当他们全都搬到了B体育馆后,有些迟到的观众并不知道演唱会已经搬走了,他们拿着票才刚来到A体育馆,对着座位号一顿找却没找到座位(椅子已经搬走了),只找到原来椅子地方剩下的一些垃圾,这时候就是迭代器失效了。

#include <iostream>
#include <vector>
using namespace std;int main()
{vector<int> concert;concert.resize(5000); //一开始只放了5000把椅子auto it = concert.begin();cout << *it << endl;concert.resize(100000); // concert.reserve(100000); 效果一样 //后来换了场地,放了100000把椅子cout << *it << endl;
}

在这里插入图片描述
可以看到,当vecor resize()了更大的空间时,会在内从中找另外一块更大的连续内存,然后将数据拷贝过去,此时,在拷贝之前初始化的迭代器 it 仍然停留在原来的地址,所以在数据搬走之后,原来地方的值已经变成了内存中的随机值了。

那么如果周杰伦自信一点,一开始就决定在B体育馆开演唱会,那么也就是一开始就 reserve() 了100000人容量,那么大家也就不会因为场地不够而搬走,迟到的观众也不会找不到座位了。

#include <iostream>
#include <vector>
using namespace std;int main()
{vector<int> concert;concert.reserve(100000); //一开始就申请100000容量concert.resize(5000); //一开始只放了5000把椅子auto it = concert.begin();cout << *it << endl;concert.resize(100000); //reserve()效果一样 //后来调整到100000把椅子cout << *it << endl;
}

在这里插入图片描述
也就是说,一开始就申请足够的容量,就不容易发生数据搬迁拷贝情况,这样,迭代器就不会失效了。

三、总结

reserve() 的作用能够避免不必要的vector扩容,从而避免迭代器失效问题。resize() 调整的是数据的有效空间,对应着size(),而reserve调整的是总容量,对应capacity()。

这篇关于STL的vector::resize() 和 vector::reserve()区别和作用详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/325942

相关文章

Mysql 中的多表连接和连接类型详解

《Mysql中的多表连接和连接类型详解》这篇文章详细介绍了MySQL中的多表连接及其各种类型,包括内连接、左连接、右连接、全外连接、自连接和交叉连接,通过这些连接方式,可以将分散在不同表中的相关数据... 目录什么是多表连接?1. 内连接(INNER JOIN)2. 左连接(LEFT JOIN 或 LEFT

Java中switch-case结构的使用方法举例详解

《Java中switch-case结构的使用方法举例详解》:本文主要介绍Java中switch-case结构使用的相关资料,switch-case结构是Java中处理多个分支条件的一种有效方式,它... 目录前言一、switch-case结构的基本语法二、使用示例三、注意事项四、总结前言对于Java初学者

Linux内核之内核裁剪详解

《Linux内核之内核裁剪详解》Linux内核裁剪是通过移除不必要的功能和模块,调整配置参数来优化内核,以满足特定需求,裁剪的方法包括使用配置选项、模块化设计和优化配置参数,图形裁剪工具如makeme... 目录简介一、 裁剪的原因二、裁剪的方法三、图形裁剪工具四、操作说明五、make menuconfig

详解Java中的敏感信息处理

《详解Java中的敏感信息处理》平时开发中常常会遇到像用户的手机号、姓名、身份证等敏感信息需要处理,这篇文章主要为大家整理了一些常用的方法,希望对大家有所帮助... 目录前后端传输AES 对称加密RSA 非对称加密混合加密数据库加密MD5 + Salt/SHA + SaltAES 加密平时开发中遇到像用户的

结构体和联合体的区别及说明

《结构体和联合体的区别及说明》文章主要介绍了C语言中的结构体和联合体,结构体是一种自定义的复合数据类型,可以包含多个成员,每个成员可以是不同的数据类型,联合体是一种特殊的数据结构,可以在内存中共享同一... 目录结构体和联合体的区别1. 结构体(Struct)2. 联合体(Union)3. 联合体与结构体的

Springboot使用RabbitMQ实现关闭超时订单(示例详解)

《Springboot使用RabbitMQ实现关闭超时订单(示例详解)》介绍了如何在SpringBoot项目中使用RabbitMQ实现订单的延时处理和超时关闭,通过配置RabbitMQ的交换机、队列和... 目录1.maven中引入rabbitmq的依赖:2.application.yml中进行rabbit

C语言线程池的常见实现方式详解

《C语言线程池的常见实现方式详解》本文介绍了如何使用C语言实现一个基本的线程池,线程池的实现包括工作线程、任务队列、任务调度、线程池的初始化、任务添加、销毁等步骤,感兴趣的朋友跟随小编一起看看吧... 目录1. 线程池的基本结构2. 线程池的实现步骤3. 线程池的核心数据结构4. 线程池的详细实现4.1 初

Python绘制土地利用和土地覆盖类型图示例详解

《Python绘制土地利用和土地覆盖类型图示例详解》本文介绍了如何使用Python绘制土地利用和土地覆盖类型图,并提供了详细的代码示例,通过安装所需的库,准备地理数据,使用geopandas和matp... 目录一、所需库的安装二、数据准备三、绘制土地利用和土地覆盖类型图四、代码解释五、其他可视化形式1.

SpringBoot使用Apache POI库读取Excel文件的操作详解

《SpringBoot使用ApachePOI库读取Excel文件的操作详解》在日常开发中,我们经常需要处理Excel文件中的数据,无论是从数据库导入数据、处理数据报表,还是批量生成数据,都可能会遇到... 目录项目背景依赖导入读取Excel模板的实现代码实现代码解析ExcelDemoInfoDTO 数据传输

如何用Java结合经纬度位置计算目标点的日出日落时间详解

《如何用Java结合经纬度位置计算目标点的日出日落时间详解》这篇文章主详细讲解了如何基于目标点的经纬度计算日出日落时间,提供了在线API和Java库两种计算方法,并通过实际案例展示了其应用,需要的朋友... 目录前言一、应用示例1、天安门升旗时间2、湖南省日出日落信息二、Java日出日落计算1、在线API2