C++STL内存管理:堆栈或堆

C++ STL Memory Management: Stack or Heap?

本文关键字:堆栈 内存 管理 C++STL      更新时间:2023-10-16

通常,当我使用非本地作用域中的STL对象时,我会存储指向要存储的数据的指针。例如

std::vector<MyStruct*> 

到了清理向量的时候,我会遍历并删除所有内容。我最近注意到,这并不像我想象的那样有必要。无论出于什么原因,我认为STL类将数据存储在堆栈上,而现在我认为它将数据分配在堆上。这是正确的吗?将对象存储为指针以减少复制时间的唯一真正好处是什么?

标准容器通过Allocator对象分配内存,该对象的类型作为模板参数传递。如果您不传递任何其他内容,则为std::allocator<T>,它将使用new来分配内存。

一句话:你可以强迫他们以任何你想的方式分配内存,但默认情况下,内存来自免费存储。

如果你真的想要一个指针容器,如果容器将拥有指针对象(例如,当对象被破坏时,将自动删除它们),你可能需要查看Boost Pointer Containers。

使用指针来减少复制时间是一个真正的好处。想想所有可以改进的向量操作,比如排序。

另一个真正的好处(如上面的评论所述)是,这允许您使用多态性,并将相关的对象存储在同一个向量中。一些你不能用标量对象(非指针)做的事情。

无论您将数据存储在堆栈还是堆上,移动该对象的成本都没有区别(嗯……确实如此,但通常可以忽略不计,在本讨论中不相关)。

将指向对象的指针存储在STL向量中时,向量不会拥有对象的所有权。你仍然需要尽职调查,在不再需要它们的时候把它们清理干净。

[…]而我现在认为它在堆上分配它。这是正确的吗?

是的。如果您将矢量声明为:

std::vector<MyStruct*> v;

那么你基本上是在向量中存储指针,所以向量会分配内存来存储指针,而不是指针指向的对象。因此,当析构函数运行时,向量将取消分配它已分配的内存,它不会取消分配它们自己的指针的内存,也就是说,它不会重新分配存储在向量中的指针所指向的内存。

但是,如果您声明:

std::vector<MyStruct> v;

然后存储对象本身,因此向量将分配内存来存储对象,并在析构函数运行时将其释放。

到了清理矢量的时候,我会仔细检查并删除每件事我最近注意到,这不像我我想是的。

不要想当然。如果向量中的指针指向动态分配的内存,那么您需要删除该内存,因为向量不会为您执行此操作。

例如,如果您的代码属于类型

 MyStruct* pNewStruct = new MyStruct;
 myVector.push_back(pNewStruct);
 ...
 ...
 myVector.clear();

内存泄漏是因为您没有专门删除分配给添加到向量中的每个元素的内存。作为动态数组的一部分,向量释放了它在自己内部分配的内存,但这只是释放指针数组,而不是指针指向的内存