vector内存分配特点

vector有一个特点:内存空间只会增长,不会减小。为了支持快速的随机访问,vector容器的元素以连续方式存放,每添加一个元素时,都需要保证连续存放的特性,若空间不足则需要重新分配空间、拷贝元素。因此在创建vector时,对其分配的内存空间比当前需要的要多一些,也就是说预留一些额外的存储空间用于存放新添加的元素。

vector有两个函数,一个是capacity(),返回对象缓冲区(vector维护的内存空间)实际申请的空间大小,另一个size(),返回当前对象缓冲区存储数据的个数。也就是说,前者是占用空间的大小,后者是其中存放数据的多少,并且capacity永远大于等于size。当两者相等时,vector就会重新分配内存,扩大capacity。

为什么要释放内存

实际上vector不需要手动释放,当超出范围或者程序结束时会自动回收,对于数据量较小的变量来说,不需要考虑内存释放的问题。但对于数据量很大,占用内存空间较多的变量,有时候需要考虑内存占用的问题。由于上面所说的性质,当某个变量已经不需要或者被clear的时候,capacity的值并没有变,所占的空间也没有变,这时就需要其他函数解决。

下面介绍两种方法。

内存释放示例

swap()函数

在《Effective STL》给出的解决方案是:

1
2
3
4
5
vector<type> v;
//.... 这里添加许多元素给v
//.... 这里删除v中的许多元素
vector<type>(v).swap(v);
//此时v的容量已经尽可能的符合其当前包含的元素数量

即先创建一个尽可能小的符合所需数据的临时拷贝,再将该拷贝与原先的vector进行交换,交换后临时变量会被销毁,内存释放。此时v就是临时拷贝,而交换后的临时拷贝是v的数据,只不过已经被销毁。下面是测试代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <vector>
using namespace std;

int main()
{
vector <int> v(1000000,1);

printf("查看内存使用情况,");
system("pause");

v.clear();

printf("查看内存使用情况,无变化。");
system("pause");

printf("swap函数前vector容量:%d\n", v.capacity());

vector <int>(v).swap(v);

printf("swap函数后vector容量:%d\n", v.capacity());

printf("查看内存使用情况,减小。");
system("pause");
return 0;
}

shrink_to_fit()函数

c++11中给出了一个新的解决方案。这个函数是专门为减小容器的容量设计的,在cplusplus中有如下定义:

Requests the container to reduce its capacity to fit its size.
The request is non-binding, and the container implementation is free to optimize otherwise and leave the vector with a capacity greater than its size.

shrink_to_fit()会在几种典型情况下放弃重分配,如元素类型不支持无异常移动、使用拷贝完成内存重分配期间某个元素构造抛出异常、重分配新位置需要的内存失败、capacity()和size()相等。此时函数回滚容器到调用前状态,错误不返回。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <vector>
using namespace std;

int main ()
{
vector<int> myvector (100);
cout << "1. capacity of myvector: " << myvector.capacity() << '\n';

myvector.resize(10);
cout << "2. capacity of myvector: " << myvector.capacity() << '\n';

myvector.shrink_to_fit();
cout << "3. capacity of myvector: " << myvector.capacity() << '\n';

return 0;
}

输出结果为:

  1. capacity of myvector: 100
  2. capacity of myvector: 100
  3. capacity of myvector: 10