UP | HOME

Ping's Tech Notes

C++ vector容器强制释放内存

Ping Zhou, 2021-11-27

换个话题,聊聊使用C++ STL vector容器时的一个内存管理问题。

C++用户经常会用STL里的vector容器来管理一组动态对象。STL vector的使用和C语言的数组类似,很方便:

std::vector<int> buf = { 0, 1, 2, 3, 4, 5 };
buf[0]++;
buf[1] = 10;

并且内存的使用和释放都由STL管理,用户不用像C语言那样手动malloc和free管理内存,确实省心不少。

但是在有些情况下,我们需要对容器占用的内存进行手动管理。

举个例子,假如我们有个数据管道,每次迭代生成一个样本池,里面有几百万个对象放在一个vector里,从中抽取一万个样本,然后交给管道作下一步处理,并且这个过程会反复进行。

那么在这个反复迭代过程中,我们希望样本池在每次采样完后就从内存里释放掉。否则下一次迭代时,我们再次生成样本池,而前一次占用的内存的还没释放掉,就有可能因为内存不够导致程序崩溃(Out Of Memory)。

你可能会问,这种情况用容器的clear方法不就好了?

但是,clear方法只是把这个容器的size变成了0,如果它的capacity其实没变,也就是说,clear方法并没有真的释放容器占用的内存。

buf.clear();

std::cout << buf.size();      // size变成了0
std::cout << buf.capacity();  // capacity还是6

那么在C++ STL里,是可以手动强制释放容器占用的内存的。方法不止一个,这里举个简单可靠的,就是用swap方法:

std::vector<int> buf = { 0, 1, 2, 3, 4, 5 };
// ......

// 强制释放buf占用的内存
std::vector<int>().swap(buf);

解释一下这个方法的原理:

之后再查看 buf.capacity() ,就会看到它也变成了0。

注:除了这个方法外,理论上我们还可以用 eraseresize 来释放内存,但这两个方法都不一定可靠,因为它们都依赖底层的 shrink_to_fit() 方法,而我们用的vector不一定实现这个方法。