vector的resize函数和reserve函数

article/2025/9/24 17:52:55

博客原文:C++基础篇 -- vector的resize函数和reserve函数_VampirEM_Chosen_One的博客-CSDN博客,写的特别好,谢谢原博主。

正文:

对于C++的vector容器模板类,存在size和capacity这样两个概念,可以分别通过vector的size()和capacity()方法获得该vector当前的size和capacity值。相应的,vector提供了两个方法来分别对size和capacity进行操作,它们就是resize方法和reserve方法。


首先,对于size和capacity,这是两个比较容易混淆的概念。都说要抱着问题来学习,才能做到事半功倍。那么,这里便提出三个问题:什么是vector的大小(即size)?什么是vector的容量(即capacity)?这两个概念的区别在哪里?


对于抽象的问题,只要我们把它们同我们的生活实际相结合,将问题具象化,自然就会很好的理解。

就拿我们的办公室举例,假设,我们部门的办公地点位于公司大楼的六楼。在我们的办公室里面,放置了100套办公桌椅(工位),公司说按照一个萝卜一个坑来算,你们部门最多只能招这么多人,那么,这时我们可以说,我们部门的容量(即capacity)就是100人,如果我们部门是公司刚成立的部门,正处于发展壮大的阶段,目前只有40为员工,也就是说,办公室里只坐了40个人,另外60个工位是空着的,那么,我们可以说,我们部门当前的大小(即size)是40人。这实际上就是size和capacity的区别。类比到vector,size和capacity的概念自然就很清楚了。


cplusplus.com中对capacity是这样定义的:

This capacity is not necessarily equal to the vector size. It can be equal or greater, with the extra space allowing to accommodate for growth without the need to reallocate on each insertion.

一个allowing道出了真谛!这里还要区分两个概念,就是:为vector分配的存储空间和vector的大小是两个不同的概念。为vector分配的存储空间,实际上就是capacity,指的是当前vector最多能使用的存储空间,是大于等于vector的大小的,当vector实际需要使用的存储空间大于当前分配给它的存储空间时,需要重新为其分配存储空间。


cplusplus.com中对size的定义是:

This is the number of actual objects held in the vector, which is not necessarily equal to its storage capacity.

实际上就是vector中当前实际存储的元素个数。


弄清楚了size和capacity这两个概念之后,对于resize和reserve两个方法就很好理解了。

cplusplus.com中对reserve的定义是:

Request a change in capacity
Requests that the vector capacity be at least enough to contain n elements.

If n is greater than the current vector capacity, the function causes the container to reallocate its storage increasing itscapacity to n (or greater).

In all other cases, the function call does not cause a reallocation and the vector capacity is not affected.

This function has no effect on the vector size and cannot alter its elements.


从上面的说明中,可以得到以下信息:

1、reserve方法被用来重新分配vector的容量大小;

2、只有当所申请的容量大小n大于vector的当前容量时,才会重新为vector分配存储空间;

3、reserve方法对于vector的大小(即size)没有任何影响;


具体通过下面的例子验证

#include <iostream>
#include <vector>using namespace std;int main()
{vector<int> vect;vect.reserve(5);    // 调用reserve方法为vect分配容量(即存储空间)vect.push_back(1);vect.push_back(2);vect.push_back(3);vect.push_back(4);  // 插入4个元素cout << vect.size() << endl;      // vect的实际大小(即包含多少元素)cout << vect.capacity() << endl;     // vect的容量大小return 0;
}

结果为

从结果中,就可以很清楚的看到capacity和size的区别。

下面看一个综合的例子,可以从中获得很多信息:

#include <iostream>
#include <vector>using namespace std;int main()
{vector<int> vect;vect.reserve(5);vect.push_back(1);vect.push_back(2);vect.push_back(3);vect.push_back(4);cout << vect.size() << endl;cout << vect.capacity() << endl;vect.push_back(5);                               vect.push_back(6);                       // 插入两个元素,此时vect的大小大于之前分配的容量5cout << "size1 = " << vect.size() << endl; cout << "capacity1 = " << vect.capacity() << endl;vect.push_back(7);vect.push_back(8);                       // 在插入两个元素,和上面的结果进行对比,会有意外收获cout << "size1_1 = " << vect.size() << endl; cout << "capacity1_1 = " << vect.capacity() << endl;vect.reserve(3);                        // 当程序执行到此处时,vect的容量大小一定是大于3的cout << "size2 = " << vect.size() << endl;cout << "capacity2 = " << vect.capacity() << endl;vect.reserve(12);cout << "size3 = " << vect.size() << endl;cout << "capacity3 = " << vect.capacity() << endl;return 0;
}

执行结果为:

对这一执行结果,一点点进行分析:

1、首先,看结果size1和capacity1,在打印这两个结果前,程序向vect中插入了两个元素,之前,vect中存在4个元素且容量为5,按照我之前的设想,如果我采用push_back向vect中插入元素时,当元素数量大小capacity时,vect的capacity会随着size变大而变大,但应该是和size相等。但此处,vect的大小为6,但是容量却是7,且这个7,来的很是突然,我往哪个方面靠都靠不上啊。好吧,先把这个疑问姑且放下,现在我们猜想,是不是push_back中针对这种情况会有处理,始终保持vect的capacity比size至少大1,带着这个猜想继续向下看,我又向vect中插入了两个元素,此时,vect的大小为8,若是我们刚才的猜想是正确的话,则此时,vect的capacity应该增大为9了,但是此时结果size1_1和capacity1_1却给了我当头一棒,这个10又是怎么回事?学习编程永远记住一件事情,所有问题的答案,都能从代码中找到。于是,我顺着vector的push_back源码开始找下去,就有了下面这段追踪代码
 

   ...
void push_back(_Ty&& _Val)...if (this->_Mylast == this->_Myend)_Reserve(1);...void _Reserve(size_type _Count)
{	// ensure room for _Count new elements, grow exponentiallysize_type _Size = size();if (max_size() - _Count < _Size)_Xlen();else if ((_Size += _Count) <= capacity());elsereserve(_Grow_to(_Size));
}size_type _Grow_to(size_type _Count) const
{	// grow by 50% or at least to _Countsize_type _Capacity = capacity();_Capacity = max_size() - _Capacity / 2 < _Capacity? 0 : _Capacity + _Capacity / 2;	// try to grow by 50%if (_Capacity < _Count)_Capacity = _Count;return (_Capacity);
}

由这段官方实现代码,终于找到了答案,原来在使用push_back向vect中插入元素时,如果当前元素数量大于vector的capacity时,会重新为vector分配存储空间,而分配的原则就是:

                    原capacity + 原capacity / 2

这样,就解释了上面的7和10两个结果,最初,vect的容量大小为5,在第一次插入两个元素后,vector中的元素数量大于5了,所以此时,会重新为vect分配容量,分配大小为5 + 5 / 2 = 7,而同样的,第二次重新分配vect的容量是7 + 7 / 2 = 10,这就合理的解决了刚才的疑问。


2、当vect的容量大小为10时,再调用reserve方法,重新为其设置容量为3时,不会进行任何操作,可以看到,vect的容量大小还是10;

3、当为vect设置容量大小为12时,可以看到,成功的改变了vect的容量大小;

4、不论哪次调用reserve方法,vect的size大小在调用前后,始终没有被改变过。


到此,是我对reserve方法的一些思考和验证。


cplusplus.com中对resize的定义是:

Resizes the container so that it contains n elements.

If n is smaller than the current container size, the content is reduced to its first n elements, removing those beyond (and destroying them).

If n is greater than the current container size, the content is expanded by inserting at the end as many elements as needed to reach a size of n. If val is specified, the new elements are initialized as copies of val, otherwise, they are value-initialized.

If n is also greater than the current container capacity, an automatic reallocation of the allocated storage space takes place.

Notice that this function changes the actual content of the container by inserting or erasing elements from it.


从上述说明中,可以得到下面的信息:

1、resize方法被用来改变vector的大小,即vector中元素的数量,我们可以说,resize方法改变了容器的大小,且创建了容器中的对象;

2、如果resize中所指定的n小于vector中当前的元素数量,则会删除vector中多于n的元素,使vector得大小变为n;

3、如果所指定的n大于vector中当前的元素数量,则会在vector当前的尾部插入适量的元素,使得vector的大小变为n,在这里,如果为resize方法指定了第二个参数,则会把后插入的元素值初始化为该指定值,如果没有为resize指定第二个参数,则会把新插入的元素初始化为默认的初始值;

4、如果resize所指定的n不仅大于vector中当前的元素数量,还大于vector当前的capacity容量值时,则会自动为vector重新分配存储空间;


还是通过代码来说话:

#include <iostream>
#include <vector>using namespace std;int main()
{vector<int> vect;int i = 0;vect.reserve(10);vect.push_back(1);vect.push_back(2);vect.push_back(3);vect.push_back(4);vect.push_back(5);vect.push_back(6);vect.push_back(7);vect.push_back(8);                               // 此时vect的size大小为8cout << vect.size() << endl;cout << vect.capacity() << endl;vect.resize(6);                                   // 此处设置vect的大小比当前vect中元素数量小,且没有指定初始化值cout << "size1 = " << vect.size() << endl;cout << "capacity1 = " << vect.capacity() << endl;for (i = 0 ; i < vect.size(); i++){cout << vect[i] << endl;}vect.resize(4, 10);                              // 此处设置vect的大小为4,比前面的6小,且指定了初始化值,看是否会改变前四个元素的值cout << "size1_1 = " << vect.size() << endl;cout << "capacity1_1 = " << vect.capacity() << endl;for (i = 0 ; i < vect.size(); i++){cout << vect[i] << endl;}vect.resize(8, 7);                         // 此处设置vect的大小为8,大于当前vect的大小4,但是小于vect的当前容量10,指定初始化值为7cout << "size2= " << vect.size() << endl;cout << "capacity2 = " << vect.capacity() << endl;for (int i = 0 ; i < vect.size(); i++){cout << vect[i] << endl;}vect.resize(10);                           // 此处设置vect的大小为10,大于当前vect的大小8,但是等于vect的当前容量10,没有指定初始化值,采用默认值cout << "size3 = " << vect.size() << endl;cout << "capacity3 = " << vect.capacity() << endl;for (int i = 0; i < vect.size(); i++){cout << vect[i] << endl;}vect.resize(12, 77);                 // 此处设置vect的大小为10,不仅大于当前vect的大小10,还大于vect的当前容量10,会为vect重新分配存储空间cout << "size4 = " << vect.size() << endl;cout << "capacity4 = " << vect.capacity() << endl;for (int i = 0; i < vect.size(); i++){cout << vect[i] << endl;}return 0;
}

上述代码的执行结果为:

由上面的执行结果,可以得到下面几个结论:

1、使用resize方法时,改变了vector中元素的个数,即vector的大小,但不会改变vector的容量大小;

2、验证了“如果resize中所指定的n小于vector中当前的元素数量,则会删除vector中多于n的元素,使vector得大小变为n;”,由size1、capacity1、size1_1、capacity1_1,可知,如果resize指定的大小n小于vector当前的大小时,会减小vector的大小,但无论resize中是否指定初始化值,都不会影响vector中原本已经存在的元素值;

3、当resize中所指定的n大于vector当前的大小,但是小于vector当前的容量大小时,会在vector后面插入适量的元素,使得vector的大小满足n,如果指定了初始值,则会把新插入的元素初始化为指定的初始值,如果没有指定初始值,则将会把新插入的元素初始化为默认初始值,即0;(由size2、capacity2、size3、capacity3得出)

4、当resize中所指定的n大于vector当前的大小,并且大于vector当前的容量大小时,会为vector重新分配存储空间,由size4和capacity4可以看出来,其中,对于capacity = 15的原因上面已经解释过,这里不再赘述。


这里再补充一点:

reserve被用来为vector设置容量大小,但是并没有创建vector中的元素对象,必须保证vector中有通过push_back或者insert等方法插入的元素后,才能访问vector中的元素;而resize被用来设置vector的大小,即元素个数,同时会创建元素对象,因此可以通过重载标识符[]来访问vector中resize所指定的大小范围内的元素,若是采用push_back或者insert方法向vector中插入元素的话,则只会在vector的尾部插入新的元素,增加vector的元素个数,扩大vector的大小


通过下述代码进行验证:

1、
 

#include <iostream>
#include <vector>using namespace std;int main()
{vector<int> vect;int i = 0;vect.reserve(10);cout << vect.size() << endl;cout << vect.capacity() << endl;vect[0] = 3;return 0;
}

首先,在使用reserve为vect设置容量大小之后,通过[]来访问 vect中的第一个元素,此时,在编译链接过程中,不会有任何问题,但是在执行的过程中会报出:

该异常信息为:vector subscript out of range,即访问vect越界了,由此可以看出,在使用reserve时并没有为vector创建任何元素对象


2、
 

#include <iostream>
#include <vector>using namespace std;int main()
{vector<int> vect;int i = 0;vect.resize(6);cout << "size1 = " << vect.size() << endl;cout << "capacity1 = " << vect.capacity() << endl;vect[5] = 17;for (i = 0 ; i < vect.size(); i++){cout << vect[i] << endl;}vect.push_back(777);cout << "size1 = " << vect.size() << endl;cout << "capacity1 = " << vect.capacity() << endl;for (i = 0 ; i < vect.size(); i++){cout << vect[i] << endl;}return 0;
}

上述代码的执行结果为:

由上述执行结果可以看出,在使用resize为vector指定大小之后,会创建元素对象,可以通过[]标识符来对元素对象进行访问,同时若是采用push_back或者insert等方法来插入元素时,实际上会在vector尾部插入新的元素,从上面的size1值的改变可以证实。

作者:VampirEM_Chosen_One
原文:原文链接
 


http://chatgpt.dhexx.cn/article/nNySAAyy.shtml

相关文章

OpenCV 图片尺寸缩放——resize函数

文章目录 OpenCV中的缩放&#xff1a;resize函数代码案例 OpenCV中的缩放&#xff1a; 如果要放大或缩小图片的尺寸&#xff0c;可以使用OpenCV提供的两种方法&#xff1a; resize函数&#xff0c;是最直接的方式&#xff1b;pyrUp&#xff0c;pyrDown函数&#xff0c;即图像…

OpenCV的resize函数优化

背景 在使用OpenCV做图像处理的时候&#xff0c;最常见的问题是c版本性能不足&#xff0c;以resize函数为例来说明&#xff0c;将size为[864,1323,3]的函数缩小一半&#xff1a; Mat img0;gettimeofday(&t4, NULL);cv::resize(source, img0, cv::Size(cols_out,rows_out)…

C++ | resize函数的用法

最近在leetcode用C刷题&#xff0c;刚遇到一题需要给重新弄一个容器&#xff0c;并给容器初始化。新建容器要在private类中声明resize函数用来初始化preSum容器。 resize函数是C中序列式容器的一个共性函数&#xff0c;vv.resize(int n,element)表示调整容器vv的大小为n&#x…

opencv的resize函数

一、Opencv官方文档中resize的描述&#xff1a; resize Resizes an image. C: void resize(InputArray src, OutputArray dst, Size dsize, double fx0, double fy0, int interpolationINTER_LINEAR ) Python: cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]]) …

resize()函数

resize()&#xff0c;设置大小&#xff08;size&#xff09;; reserve()&#xff0c;设置容量&#xff08;capacity&#xff09;; size()是分配容器的内存大小&#xff0c;而capacity()只是设置容器容量大小&#xff0c;但并没有真正分配内存。 打个比方&#xff1a;正在建造…

OpenCV 图像缩放:cv.resize() 函数详解

目录 系列前言API函数详解参数列表缩放方式其一缩放方式其二两种方式的优先级关于插值方式 扩展 —— 相关函数 系列前言 这个系列是我第一个想要更下去的系列。每篇会全面介绍一个 OpenCV 函数&#xff0c;会给出 API 和示例。示例主要是用 Python 去写&#xff0c;但是 Open…

安卓中的几种线程间通信方式

一&#xff1a;Handler实现线程间的通信 andriod提供了 Handler 和 Looper 来满足线程间的通信。例如一个子线程从网络上下载了一副图片&#xff0c;当它下载完成后会发送消息给主线程&#xff0c;这个消息是通过绑定在主线程的Handler来传递的。 在Android&#xff0c;这里的…

Java中的线程通信的几种方式

Java中的线程间通信是指不同线程之间相互协作&#xff0c;以完成一些复杂的任务或实现某些功能的过程。线程间通信主要包括两个方面&#xff1a;线程之间的互斥和同步&#xff0c;以及线程之间的数据共享和通信。Java提供了多种方式来实现线程间通信&#xff0c;本文将介绍Java…

创建线程的四种方式 线程通信

文章目录 1.1 创建线程1.1.1 创建线程的四种方式1.1.2 Thread类与Runnable接口的比较1.1.3 Callable、Future与FutureTask 1.2 线程组和线程优先级1.3 Java线程的状态及主要转化方法1.4 Java线程间的通信1.4.1 等待/通知机制1.4.2 信号量1.4.3 管道 1.1 创建线程 1.1.1 创建线…

【多线程间几种通信方式】

一、使用 volatile 关键字 基于 volatile 关键字来实现线程间相互通信是使用共享内存的思想。大致意思就是多个线程同时监听一个变量&#xff0c;当这个变量发生变化的时候 &#xff0c;线程能够感知并执行相应的业务。这也是最简单的一种实现方式 代码案例 package com.han…

线程之间的通信方式

前言 我只是个搬运工&#xff0c;尊重原作者的劳动成果&#xff0c;本文来源下列文章链接&#xff1a; https://zhuanlan.zhihu.com/p/129374075 https://blog.csdn.net/jisuanji12306/article/details/86363390 线程之间为什么要通信&#xff1f; 通信的目的是为了更好的协…

Java线程间的通信方式

文章目录 线程间通信的定义一、等待—通知&#xff08;1&#xff09;等待—通知机制的相关方法&#xff1a;&#xff08;2&#xff09;注意事项&#xff1a;&#xff08;4&#xff09;notify()方法的核心原理&#xff08;5&#xff09;等待—通知机制的经典范式&#xff08;6&a…

线程间实现通信的几种方式

目录 线程通信相关概述提出问题方式一&#xff1a;使用Object类的wait() 和 notify() 方法方式二&#xff1a;Lock 接口中的 newContition() 方法返回 Condition 对象&#xff0c;Condition 类也可以实现等待/通知模式方法三&#xff1a;使用 volatile 关键字方法四&#xff1a…

线程间的通信方式

对共享数据进行更改的时候&#xff0c;先到主内存中拷贝一份到本地内存中&#xff0c;然后进行数据的更改&#xff0c;再重新将数据刷到主内存&#xff0c;这中间的过程&#xff0c;其他线程是看不到的。 1、为什么需要线程通信 线程是操作系统调度的最小单位&#xff0c;有自…

进程和线程的几种通信方式

进程之间通信的几种方式 1. 管道&#xff1a;是内核里面的一串缓存 管道传输的数据是单向的&#xff0c;若相互进行通信的话&#xff0c;需要进行创建两个管道才行的。 2. 消息队列&#xff1a; 例如&#xff0c;A进程给B进程发送消息&#xff0c;A进程把数据放在对应的消息队…

线程的几种通信方式

目录 一、Object的wait()、notify()、notifyAll()方法 二、Condition的await()、signal()、signalAll()方法 三、CountDownLatch 四、CyclicBarrier 五、Semaphore 线程间的通信方式常用的有如下几种&#xff1a; Object的wait()、notify()、notifyAll()方法&#xff1b; …

线程间的通信方法

线程间的通信方法 1. 线程通信简介 一般而言&#xff0c;在一个应用程序&#xff08;即进程&#xff09;中&#xff0c;一个线程往往不是孤立存在的&#xff0c;常常需要和其它线程通信&#xff0c;以执行特定的任务。如主线程和次线程&#xff0c;次线程与次线程&#xff0c…

Matlab基本操作函数 abs函数

分享一下我老师大神的人工智能教程&#xff01;零基础&#xff0c;通俗易懂&#xff01;http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章。分享知识&#xff0c;造福人民&#xff0c;实现我们中华民族伟大复兴&#xff01; 1、abs函数&#xff1a;数值的绝对值和复数…

MATLAB中FFT的整理

作为一个资深的健忘症患者&#xff0c;需要把每次用都忘记的FFT问题进行整理。 FFT可将信号从时域转换到频域。 首先是一些简单常识&#xff1a; 采样周期&#xff1a;两次采样之间的时间间隔。 采样频率&#xff1a;1/采样周期。每秒采样的点数。&#xff08;注意&#xff1a…

matlab中abs函数,matlababs是什么意思 是是是什么意思

matlababs是什么意思 是是是什么意思以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! matlab 中的abs函数什么意思 编程知识 matlab中的abs(x)是去绝对值的函数 例如:x=-1.23 abs(x) ans 1.23 以上即是取了-1.23…