std::vector在调用clear方法后是否会释放内存?

70

假设我有一个结构体的std::vector。如果调用clear()函数,内存会发生什么变化?

std::vector<myStruct> vecs;
vecs.resize(10000);
vecs.clear();

这段内存会被释放,还是作为可重用的缓冲区仍然附加到vecs变量上?


谢谢大家。我希望内存被释放 - 保证。因此,我使用new std:vector<myStruct>来分配向量,然后在完成后调用delete。这样可以保证内存被释放。 - user236520
4
@AndrewS.: 动态分配的唯一影响是引入了一种低效率。请参考Jerry的答案,了解一种合理的清空向量的方式。在循环体中,另一种好的方法是将向量局部化到循环体内部,即在循环体内声明它。 - Cheers and hth. - Alf
仅出于兴趣,为什么需要保证内存被释放? - deworde
因为这是iOS操作,我试图在更有限的平台上节约内存。 - user236520
5个回答

80
记忆仍然与向量相关联。这不仅仅是可能的,而且是必需的。特别是,如果在调用clear()之后再次向向量添加元素,则在添加的元素数量超过之前的10000时,向量必须不重新分配内存。
如果你想释放内存,通常的做法是与一个空向量进行交换。C++11还添加了一个shrink_to_fit成员函数,旨在提供类似的功能,但它是非绑定的(换句话说,它可能会释放额外的内存,但并非真正需要这样做)。

对我来说它不起作用。我有一个结构体向量,图像是结构体的一个元素。通过执行 shrink_to_fit,它并没有释放GPU或RAM。 - BarzanHayati

38

向量的内存不保证被清除。在清除后,您不能安全地访问元素。为确保内存被释放,Scott Meyers建议执行以下操作:

vector<myStruct>().swap( vecs );

Cplusplus.com对此的解释如下:

清空容器中的所有元素,调用它们各自的析构函数,并将容器的大小设置为0。

向量容量不会改变,也不会因调用此函数而进行重新分配。一种常见的替代方法是使用swap:...


它不是保证被清除了吗?还是保证不会被清除?这两者是非常不同的! - Matthew M.
是的,它保证不会被清除。答案是误导性的。 - galinette

10

析构函数被调用以释放对象,但内存仍然被分配。


7

4
可以使用它,但是标准规定它不会强制释放额外的内存(§23.3.6.3/6):“shrink_to_fit是一个非约束性请求,用于将capacity()减少到size()。” - Jerry Coffin
1
因此,它与resize(0)一样好,可能会释放内存的副作用。 - Marcus Müller
8
不,resize(0)保证会保留内存。 - Davis Herring
resize(0) 最好不要有那种副作用!如果把这个留给机会,那将是一个可怕的决定。 - Matthew M.

5

.resize(0).clear() 不会释放或重新分配已分配的内存,它们只将向量调整为零大小,同时保留相同的容量。

如果我们需要释放(释放)内存进行清除,可以使用以下操作:

在线尝试!

v = std::vector<T>();

这里调用了&&重载的=运算符,它具有类似于使用swap()解决方案的移动行为。

当存在&&重载的=运算符时,该赋值技巧可以发挥作用。在所有C++11 STD库中保证存在,请看这里。因此,如果您使用-std=c++11(gcc/clang)或/std:c++11(msvc)开关(或更高版本)编译,则我的解决方案可保证有效。


但问题实际上是“是否必须这样做?”而不仅仅是在此代码、编译器、设置等情况下是否会发生。如果赋值足够,为什么Meyers等人会推荐使用swap() - underscore_d
1
@underscore_d 是的,我的赋值代码总是在最近的编译器中清除和释放内存。可能 Meyers 使用 swap() 是因为他的书相当古老,那时还没有 && 右值引用。因为如果没有 && 赋值运算符重载,我的赋值将无法工作,而这种重载已经存在于所有 STD 库中多年了。&& 在所有 C++11 STD 库中都有保证,请看这里 - Arty

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接