缩小 std::vector 的大小以适应其实际数据以节省内存使用?vec.swap() 在 MSVC 中不起作用?

Shrink std::vector 's size to fit its actual data to save memory usage? vec.swap() doesn't work in MSVC?

本文关键字:swap vec 不起作用 MSVC 内存 数据 vector std 缩小 节省      更新时间:2023-10-16

实际上,我的程序中有数百万个向量对象。默认情况下,对于每个矢量,系统将分配比实际需要更多的空间,因为这些矢量在完成加载后是只读的。

所以我想缩小它们的容量以节省内存。一种典型的方法是使用vector.swap()方法,如本问题所述:

 std::vector<T> tmp(v);    // copy elements into a temporary vector
           v.swap(tmp);              // swap internal vector data

我试过这个代码,但发现.swap()操作实际上并没有降低内存成本。(我查看了任务管理器中的专用工作集大小,以获取进程的内存使用情况)

为什么更新"我使用的是VS2008,我添加了一些行以在运行时输出当前容量。正如下面的代码及其输出所示,交换后vec.cacapacity确实缩小到了10,但这并没有反映在任务管理器中。

或者就像@Adam Rosenfield所说的那样,这一改变并没有将释放的空间归还给操作系统?或者我不应该使用任务管理器来查找它的内存使用情况?我希望这个swap()操作能像delete pointer_to_a_big_vec一样直接释放内存。

我的测试样本在这里:

void vecMemoryTest()
{
  vector<int> vec;
  //make it big!
  for(int i = 0; i <= 100000; i++){vec.push_back(i);}
  for(int i = 0; i <= 100000; i++){vec.push_back(i);}
  cout << "Before .resize() : " << vec.capacity() << endl;
  //OK now I only need the first 10 elements
  vec.resize(10);   
  cout << "After .resize() : " << vec.capacity() << endl;
  //So try to free other spaces
  vector<int> tmp(vec.begin(), vec.end());

  vec.swap(tmp);    // now should free wasted capacity
            // But in fact it doesn't
  cout << "After .swap() : " << vec.capacity() << endl;
}

输出为:

resize()之前:207382After.resize():207382swap()之后:10

检查矢量的capacity()。你很可能会发现向量实际上减少了它的内存使用。您看到的可能是malloc()实现没有将内存释放回操作系统。

工作集计数器只考虑提交的虚拟地址空间。它没有考虑该地址空间的个人用户如何使用它

一个信息量稍大的测试是多次运行vecMemoryTest()并跟踪工作集。如果它在第一次运行后没有上升,那么您就知道您正在适当地释放内存。如果它真的上升了,它可能意味着什么。

一个更好的测试是修改vecMemoryTest(),再次分配一个相同大小的巨大vector,然后销毁它。如果工作集(大部分)保持不变,你就知道你正确地缩小了原始vector

我还没有看过实现,但vector的复制构造函数也可能复制容量。

使用迭代器形式构建新的临时:

vector<int> tmp(vec.begin(), vec.end());
vec.swap(tmp);

C++11提供了std::vector::shrink_to_fit,您可能想尝试一下。此函数要求缩小矢量的容量,以适应其所保存数据的大小但是,实现没有绑定到此请求,因此您必须检查它的行为。

如果你想避免"阻塞"保留,你必须研究标准库的专门实现;例如,用于游戏开发的可能会提供您需要的功能。

重要的是要记住,当您使用new请求内存时,操作系统通常会提供比您请求的更多的内存。这可能会对你所看到的产生一些影响。

您正在使用Visual Studio 2010吗?如果是这样的话,它支持C++0x的向量新方法shrink_to_fit。请参阅MSDN链接。