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

相关文章

C++ move 的作用详解及陷阱最佳实践

《C++move的作用详解及陷阱最佳实践》文章详细介绍了C++中的`std::move`函数的作用,包括为什么需要它、它的本质、典型使用场景、以及一些常见陷阱和最佳实践,感兴趣的朋友跟随小编一起看... 目录C++ move 的作用详解一、一句话总结二、为什么需要 move?C++98/03 的痛点⚡C++

MySQL中between and的基本用法、范围查询示例详解

《MySQL中betweenand的基本用法、范围查询示例详解》BETWEENAND操作符在MySQL中用于选择在两个值之间的数据,包括边界值,它支持数值和日期类型,示例展示了如何使用BETWEEN... 目录一、between and语法二、使用示例2.1、betwphpeen and数值查询2.2、be

python中的flask_sqlalchemy的使用及示例详解

《python中的flask_sqlalchemy的使用及示例详解》文章主要介绍了在使用SQLAlchemy创建模型实例时,通过元类动态创建实例的方式,并说明了如何在实例化时执行__init__方法,... 目录@orm.reconstructorSQLAlchemy的回滚关联其他模型数据库基本操作将数据添

Java中ArrayList与顺序表示例详解

《Java中ArrayList与顺序表示例详解》顺序表是在计算机内存中以数组的形式保存的线性表,是指用一组地址连续的存储单元依次存储数据元素的线性结构,:本文主要介绍Java中ArrayList与... 目录前言一、Java集合框架核心接口与分类ArrayList二、顺序表数据结构中的顺序表三、常用代码手动

Spring Boot Interceptor的原理、配置、顺序控制及与Filter的关键区别对比分析

《SpringBootInterceptor的原理、配置、顺序控制及与Filter的关键区别对比分析》本文主要介绍了SpringBoot中的拦截器(Interceptor)及其与过滤器(Filt... 目录前言一、核心功能二、拦截器的实现2.1 定义自定义拦截器2.2 注册拦截器三、多拦截器的执行顺序四、过

JAVA线程的周期及调度机制详解

《JAVA线程的周期及调度机制详解》Java线程的生命周期包括NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING和TERMINATED,线程调度依赖操作系统,采用抢占... 目录Java线程的生命周期线程状态转换示例代码JAVA线程调度机制优先级设置示例注意事项JAVA线程

详解C++ 存储二进制数据容器的几种方法

《详解C++存储二进制数据容器的几种方法》本文主要介绍了详解C++存储二进制数据容器,包括std::vector、std::array、std::string、std::bitset和std::ve... 目录1.std::vector<uint8_t>(最常用)特点:适用场景:示例:2.std::arra

C++构造函数中explicit详解

《C++构造函数中explicit详解》explicit关键字用于修饰单参数构造函数或可以看作单参数的构造函数,阻止编译器进行隐式类型转换或拷贝初始化,本文就来介绍explicit的使用,感兴趣的可以... 目录1. 什么是explicit2. 隐式转换的问题3.explicit的使用示例基本用法多参数构造

Android使用java实现网络连通性检查详解

《Android使用java实现网络连通性检查详解》这篇文章主要为大家详细介绍了Android使用java实现网络连通性检查的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录NetCheck.Java(可直接拷贝)使用示例(Activity/Fragment 内)权限要求

MyBatis中的两种参数传递类型详解(示例代码)

《MyBatis中的两种参数传递类型详解(示例代码)》文章介绍了MyBatis中传递多个参数的两种方式,使用Map和使用@Param注解或封装POJO,Map方式适用于动态、不固定的参数,但可读性和安... 目录✅ android方式一:使用Map<String, Object>✅ 方式二:使用@Param