admin管理员组文章数量:1612098
要说清这个问题,先抛出另外一个问题:vector和普通的数组有什么区别?
你可能会说:大家都知道,vector是动态数组~~
没错! 但是怎么个动态法?怎么实现的?
好,先说一下普通数组,比如:int arr[10]或者int *arr = new int[10]; 其实是你到内存里占了10个int大小的地方(空间);
当然,你可以这样操作:int a = arr[100]; arr[100] = 10; 这样编译器并不会报错,最多会警告你----你有越界行为。
也就是说,你一开始说好了,你只占10个大小的地方,后来你出尔反尔,又去访问或者操作第100个地方(为了说明问题,事实上是第101个),那么内存的“管理员”他没有不让你操作的权利,只是给你出示了“黄牌警告”,告诉你:你去操作吧,出了问题概不负责!!!
这就是数组越界问题,越界会造成未知的问题(程序崩溃等等),即你写的程序不受你控制了,或者不是你想要的结果(比如:你越界访问的地方是别人的地方,如果别人也没做“防护”,那么你修改了那个地方的值,就会让别人的会出现未知错误)。为了避免这个问题,那就老老实实的在那个10个大小的地方活动。
但是,在实际应用中,程序员的确有这样的需求:我开始是分配了10个大小的地方,但是我想给它后面添加一个或者给中间某个位置插入一个,变成连续11个数值。
我再描述一下这个需求:在一个连续的数组添加元素,还能保证新的数组仍然在内存连续,也就是说用下标可以访问(arr[10]访问第11个元素)。
vector就实现了这样的功能,当然vector功能不止这一个,还有很多操作(push_back,insert等)。
那么,vector是怎么实现这样的功能的?可以参考《STL源码剖析》
我们以push_back()为例,
其中size就是实际存入数据空间的大小,capacity是容量,即能容纳的数据个数。下面看一下push_back()的过程:
在insert_aux里:
这个过程就是容量扩充(备用空间不够了,就重新开辟更大的空间,把旧的拷贝进去,再把旧的释放了,有了更大的新空间,就可以连续的插入和追加元素了)
所以这个过程:重新配置->拷贝数据->释放旧的空间
如果每添加一个元素都这样操作,那效率太低了,索性一次多分分配些空间。
但是注意:
1.vector可以用下标访问元素,但是,只能访问size以内的(比如,size=10,capacity=15,就不能arr[12]这样会报错)
2.一旦扩容,原来空间就已经不存在了,数组首地址也不存在了,因为旧的被复制到新的空间,旧的就被释放了。
下面回归正题:size和capacity有什么区别?
size是真实元素的所占的空间打开,capacity是整个可容纳的空间大小;
如第一个图:
size = finish - start
capacity = end_of_storage - start
下面看一下不同编译器capacity大小分配情况:
这是vs2017的运行结果:
vector<int> arr(10,1);//10个空间,初值都是1
cout << "size=" << arr.size() << endl;
cout << "capacity=" << arr.capacity() << endl;
arr.push_back(2);//向后面添加一个元素2
cout << "size=" << arr.size() << endl;
cout << "capacity=" << arr.capacity() << endl;
这是ubantu16,g++ 5.4的运行结果:
为什么capacity不一样呢?
这个编译器有关系,在《STL源码剖析》上可以找到答案:
但是再vs2017上,capacity在满的时候,扩充的大小为原来的一半,而不是2倍。
===============================分隔线 2019.7.4=====================================================
【问题】怎么使capacity值为0?
先看代码,再讨论
#include "stdafx.h"
#include<vector>
#include<iostream>
void vector_test()
{
std::vector<int> arr(10,1);
std::cout << "arr(10,1):size=" << arr.size() << "; capacity=" << arr.capacity() << std::endl;
arr.push_back(5);
std::cout << "arr.push_back(11):size=" << arr.size() << "; capacity=" << arr.capacity() << std::endl;
arr.clear();
std::cout << "arr.clear():size=" << arr.size() << "; capacity=" << arr.capacity() << std::endl;
//arr.resize(0);
//std::cout << "arr.resize(0):size=" << arr.size() << "; capacity=" << arr.capacity() << std::endl;
//arr.reserve(0);
std::cout << "arr.reserve(0):size=" << arr.size() << "; capacity=" << arr.capacity() << std::endl;
std::vector<int>(arr).swap(arr);
std::cout << "vector<int>(arr).swap(arr):size=" << arr.size() << "; capacity=" << arr.capacity() << std::endl;
}
void Test()
{
vector_test();
}
int main()
{
Test();
getchar();
return 0;
}
1.为什么要把capacity值变为0?
答:当vector容器不断的插入,capacity也不断的扩张,其实capacity是占着内存的,有时候用不了那么多,岂不是很浪费?所以怎么修改capacity的值,也就是我们手动的释放不使用的空间。capacity变为0只是经常会被问到,变为0都会了,变为其他值就是照猫画虎。
2.怎么变?
利用vector的拷贝构造函数。(1)vector的拷贝构造函数,只分配拷贝的元素需要的内存;(2)因为产生临时对象,然后和原来对象进行交换。(3)临时对象消失。
收先验证拷贝构造函数,只分配拷贝的元素需要的内存:
std::vector<int> arr1 = std::vector<int>(arr);
std::cout << "arr1:size=" << arr1.size() << "; capacity=" << arr1.capacity()<<std::endl;
然后交换:
交换前需要使用clear,将容器清零。
arr.clear();
std::vector<int> arr1 = std::vector<int>(arr);
arr1.swap(arr);
也可一步到位:
std::vector<int>(arr).swap(arr);
另外记录一下resize和reserve这两个函数:
resize是调整size的大小,如果size调整到比原来小,capacity的值不会变化;如果size调整的比原来大,则遵循push_back的扩容原则。
reserve是调整预分配空间的大小,如果调整比原来擦capacity小,依然还是原来capacity的大小。
https://wwwblogs/chailu/p/6179263.html
本文标签: 有什么区别值为VectorsizeCapacity
版权声明:本文标题:vector的size和capacity有什么区别?怎么使capacity值为0? 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dongtai/1728619498a1166165.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论