关于c ++:关于向量和删除与他们相关的内存的问题

Questions About Vectors and Deleting Memory Associated With Them

几个月前我用向量法写了一个程序。我使用clear()成员函数"重置"向量,假设它不仅可以清除元素中的项并重置大小数据成员,而且还可以向堆返回以前与它一起使用的内存。好吧,我偶然发现了一篇关于向量的文章,说这不是从向量中获取内存的正确方法,因为使用clear()不会做到这一点,但需要使用交换方法:

1
vector<MyClass>().swap(myVector);

我很好奇为什么我们要调用交换来删除旧的内存?我认为这更像是一种权宜之计,因为我们正在使用交换,但其他事情正在发生。是否调用了析构函数?

最后一个问题是,我现在读到的所有文章都说clear()不会释放内存,即对象被"销毁"。有人能解释这是什么意思吗?我对白话不熟悉。我假设如果一个对象被破坏了,它就被清除了,内存又被返回到堆中,但是这是错误的,"破坏"这个词是指仅仅删除与每个元素相关的位吗?我不确定。任何帮助都将不胜感激。谢谢。


要回答这个问题,您需要将vector直接分配的内存与通过成员对象间接"拥有"的内存分开。例如,假设MyClass是一个占用1000字节的对象,然后使用std::vector>。然后,如果该向量有10个元素,那么在64位系统上,直接分配的内存通常接近10*8=80字节,而unique_ptr对象间接拥有10*1000=10000字节。

现在,如果您在向量上调用clear(),则在每个unique_ptr元素上调用析构函数,从而释放10000个间接拥有的字节。但是,底层数组存储没有释放,因此向量直接拥有的80+字节仍然被分配。(此时,向量的capacity()至少为10,但size()至少为0。)如果随后调用向量的析构函数,这也将导致释放存储数组。

现在,如果你执行

1
std::vector<std::unique_ptr<MyClass>>().swap(v);

让我们来分解它的作用:首先,创建一个临时的向量对象,它没有分配数组,capacity()为0。现在,swapv的底层数组转移到临时向量,并将空数组或空数组从临时向量交换到v中。最后,在表达式的末尾,临时对象超出了范围,因此调用了其析构函数。这会导致调用以前属于v的任何元素的析构函数,然后释放以前属于v的底层数组存储。因此,在结束时,v.capacity()为0,所有以前属于v的内存都被释放,不管它是由v直接分配的还是通过存储的unique_ptr对象间接属于它。


vector有一个关联的量,称为capacity,这意味着它已经为许多元素分配了足够的内存,即使它目前实际上不包含那么多元素。

如果在不超过容量的情况下从向量中添加或移除元素,则不会分配或释放内存;个别元素的构造函数和析构函数将在已分配的空间上运行。

clear()功能不会改变容量。但是,通常的vector::swap()的实现也会交换向量的容量;因此,与空向量交换将导致原始向量具有默认容量,该容量将很小甚至为零(依赖于实现),因此应释放内存。

由于C++ 11有一种减少容量的正式方法,称为SyrStutoFig()。

请注意,C++标准实际上并不要求在减少容量之后将内存释放到OS上,这将取决于您使用的库实现的作者和操作系统的组合。