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);
解释一下这个方法的原理:
- 首先用
std::vector<int>()
生成一个空的列表,其容量为0; - 然后用它和buf进行交换(
swap
方法); - 因为空列表的内存占用是0,buf和它交换后就会被强制释放。
之后再查看 buf.capacity()
,就会看到它也变成了0。
注:除了这个方法外,理论上我们还可以用 erase
或 resize
来释放内存,但这两个方法都不一定可靠,因为它们都依赖底层的 shrink_to_fit()
方法,而我们用的vector不一定实现这个方法。