C++知识点——vector::reserve()函数

参考:
1)https://blog.csdn.net/sinat_38183777/article/details/82056289
2)https://blog.csdn.net/manonggou/article/details/106097630
3)https://blog.csdn.net/qq_37037492/article/details/86568290

下面内容引用于参考1)

1 reserve的优势

函数原型:

/**
*@function 申请n个元素的内存空间
*@param n  元素个数
*/
void reserve (size_type n);

"vector函数的作用就是申请内存空间,vector是一种可以自动扩展的容器,也就是可以根据元素个数自动申请内存,那么有什么必要去主动为它申请内存空间呢?答案是有必要的,我们来看个例子。假如要使用vector存储1000个数据:

方式1:vector vec, 然后调用1000次 vec.push_back();
方式2:vector vec,然后调用vec.reserve(1000)申请1000个元素的内存,再调用1000次 vec.push_back(
);

方式1要进行若干次内存分配;而方式2只需要进行1次内存分配。其效率立见高下,所以在需要对大量数据进行处理的时候,使用reserve主动分配内存可以提升程序执行效率"

2 异常处理

我们在使用这个函数的时候,如果申请的内存比较大的话就需要注意,如果处理不当程序很可能会出现崩溃。例如点云数据很容易上百万级,需要的内存就比较大了。

我们查看reserve这个函数,资料说它能传入的最大数据是max_size,等于1073741823,当传入的参数比它大时就会抛出一个 length_error异常。这是一个很大的数,我们可以简单的做一个计算,如果存储的数据类型为int型,每个int数据占用4个字节,max_size个int数据就相当于4096GB。想想我们怎么也不可能申请这么大的内存,所以这个异常是极少出现的。但是我们传入远远小于max_size的参数时程序也会出现崩溃,这是为什么呢?这就是因为除了这个异常,还有另一个异常也会导致程序出错。

内存的分配不只受到reserve函数参数的限制,更受到电脑总内存的限制,一般的电脑内存也就4GB、8GB,操作系统、应用程序执行也需要一部分内存,剩下的内存才是能够给reserve分配的。然后我们认为操作系统和应用程序大概也就用2GB的内存吧,那还剩下至少2GB的内存,我不申请2GB,我申请1GB总行吧,但是结果很令人沮丧,程序出现异常。我做了一个实验,申请的内存大概到200MB的时候就有一定概率出现异常。我的理解是vector的内存是连续的,电脑中虽然还剩下比较多的内存,但是连续的内存却只有几百MB,所以最多只能申请那么多内存,多了就会失败。你已经看出来了,这个异常就是bad_alloc,分配内存失败。

reserve这个函数是能抛出异常的,如果我们没有去捕获这个异常,那么程序运行到这里就直接崩溃了,加上异常捕获就能避免这个问题,只要输出异常信息或在软件界面上给出用户提示信息就可以了。另一个就是要尽量限制传入参数的值,减少出现异常的情况。

所以一定要对异常处理有一个清晰的认识,有时候软件崩溃或许就是因为你没有对能抛出异常的函数进行异常处理,而这些问题又不算真正的bug,让你陷入错误的解决道路中。所以一条有用的定律就是凡是有异常抛出的函数都加上异常处理。

3 reverse和resize区别

以下内容引用于参考2)
一、resize
1、resize(n)
调整容器的长度大小,使其能容纳n个元素。
如果n小于容器的当前的size,则删除多出来的元素。否则,添加采用值初始化的元素。
2、 resize(n,t)
多一个参数t,将所有新添加的元素初始化为t。

二、reserve
reserver()的用法只有一种:reserve(n)
预分配n个元素的存储空间。

size(长度):指容器当前拥有的元素个数;
capacity(容量):则指容器在必须分配新存储空间之前可以存储的元素总数,也可以说是预分配存储空间的大小。

容器调用resize()函数后,所有的空间都已经初始化了,所以可以直接访问。而reserve()函数预分配出的空间没有被初始化,所以不可访问。
1)resize()函数对vector的影响。
size:调用resize(n)后,vector的size即为n,且其中元素都为0。
capacity:取决于调整后的容器的size是否大于capacity。如果调整后size大于capacity,则capacity调整为size大小,否则不变

2)reserve()函数对vector影响
capacity:调用reserve(n)后,若容器的capacity<n,则重新分配内存空间,从而使得capacity等于n。如果capacity>=n呢?capacity无变化。

例子:

vector<int> a;
 
a.reserve(100); 
a.resize(50);
cout<<a.size()<<"  "<<a.capacity()<<endl; // 50 100
a.push_back(1);
cout << a.size() << "  " << a.capacity() << endl; // 51 100
a.resize(150);
cout<<a.size()<<"  "<<a.capacity()<<endl;// 150 150
a.reserve(50);
cout<<a.size()<<"  "<<a.capacity()<<endl;// 150 150
a.resize(50);
cout<<a.size()<<"  "<<a.capacity()<<endl;// 50 150

下面部分引用于参考1)
看到第一部分方式2,我们可能会有疑问,它不是相当于vector vec(1000),,然后调用1000次 vec.push_back();或者,int arr[1000],然后调用arr[i]=;*

No!效果是一样的,都是一次性分配内存,效率很高,但是它们同方法2存在本质的区别。reserve方法是只分配内存,不创建对象,而这两种方法都创建了1000个int类型的对象。(创建了对象就赋上了初值0)****

同样,resize函数正是在分配内存的同时会创建对象。

感觉它们的功能都大同小异,那么什么情况下使用哪一个函数比较好呢?我自己的意见是在能用reserve的情况下都用reserve,只能用resize的情况下用resize,因为使用reserve只需要赋一次值(调用push_back的时候),而resize需要赋两次值(初始化和调用push_back的时候)。哪种情况下只能用resize呢?就是当vector已经有数据,需要扩展数据的时候

以下内容引用参考3)

resize和reserve函数本质都涉及了vector的内存存储空间,因为vector在内存中是连续存放的,所以当resize的空间大于现有的存储空间(capacity() 函数 返回当前vector在重新进行内存分配以前所能容纳的元素数量.)时,会重新选择更大的空间,并将所有元素复制过去。resize在初始化内存容量时有对值的初始化,所以此时push_back会产生size+1,内存容量不够,重新寻找更大的内存空间并复制所有元素,所以这个过程是很费事的。

事先没有指定capacity,只指定size,capacity可能会随着size变化。

vector<int> vec1(500);
vec1.push_back(1);
cout << vec1.size() << endl; // 500
cout << vec1.capacity() << endl;  // 750(这个值不确定)

vector<int> vector1;
vector1.resize(20);
vector1.push_back(1);
vector1.push_back(2);
vector1.push_back(3);
cout << "vector1的长度:" << vector1.size() << endl;//vector1的长度:23
cout << endl << "当前vector数量:" << vector1.capacity() << endl; 
vector<int> vector2;
vector2.reserve(10);
vector2.push_back(1);//vector1的长度:3
vector2.push_back(2);//1 2 3
vector2.push_back(3);
cout << "vector2的长度:" << vector2.size() << endl;//vector2的长度:13
for_each(vector2.begin(), vector2.end(), [](int x) {cout << x << " "; });//0 0 0 0 0 0 0 0 0 0 1 2 3

  • 25
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值