vector的size和capacity有什么区别?

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/pengshengli/article/details/86287794

要说清这个问题,先抛出另外一个问题: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

下面看一下不同编译器capacit大小分配情况:

这是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的运行结果:

为什么一样呢?

这个编译器有关系,在《STL源码剖析》上可以找到答案:

但是再vs2017上,capacity在满的时候,扩充的大小为原来的一半,而不是2倍。

猜你喜欢

转载自blog.csdn.net/pengshengli/article/details/86287794