缩小 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?
实际上,我的程序中有数百万个向量对象。默认情况下,对于每个矢量,系统将分配比实际需要更多的空间,因为这些矢量在完成加载后是只读的。
所以我想缩小它们的容量以节省内存。一种典型的方法是使用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链接。
- 在for循环中使用auto vs decltype(vec.size())来处理字符串的向量
- 是否可以在 C++03 中定义'move-and-swap idiom'等效项
- 如何使 std::sort 在 std::swap 和我的命名空间的模板化交换之间没有名称冲突?
- 我可以使用 std::vector::swap 来修改共享向量吗?
- Valgrind 在 std::string::swap 中报告 SIGILL
- Omnet++中的.vec和.sca输出有什么区别?
- vec[i][j] 是否转换为 *(vec + i + j)?
- 对函数的 out 字符串参数使用 swap 与赋值
- 使用 std::vector::swap 方法在C++中交换两个不同的向量是否安全?
- 如何在编译器C++不智能的情况下实现 GLSL vec* 构造语法?
- a,b = b,a in python vs std::swap() in C++
- 使用 std::swap 禁用 ADL
- 如何使用 std::swap with array?
- 为什么 std::swap 不适用于<bool> Clang/Win(英语:Clang/Win)下的矢量元素?
- 在Rcpp(和RcppArmadillo)中,如何检查vec是否包含复数
- swap(int&, int&) 函数不起作用,当交换不使用临时变量时?
- c++14 - vec.begin() 和 begin(vec) 之间有什么区别吗?
- 智能指针的 std::swap 是否保证引用保持不变?
- 是否可以使用 std::vector<std::any> vec;这将导致异构数据类型
- 缩小 std::vector 的大小以适应其实际数据以节省内存使用?vec.swap() 在 MSVC 中不起作用?