C++ STL 内存管理:堆栈还是堆?
Posted
技术标签:
【中文标题】C++ STL 内存管理:堆栈还是堆?【英文标题】:C++ STL Memory Management: Stack or Heap? 【发布时间】:2012-07-28 09:49:25 【问题描述】:通常,当我使用非本地范围内的 STL 对象时,我会存储指向我想要存储的数据的指针。比如
std::vector<MyStruct*>
当需要清理向量时,我会检查并删除所有内容。我最近注意到这并不像我想象的那样是必要的。无论出于何种原因,我一直认为 STL 类将数据存储在堆栈上,而我现在认为它是在堆上分配数据的。它是否正确?将对象存储为指针以减少复制时间是唯一真正的好处吗?
【问题讨论】:
std::vector<Shape *>
可以存储Circle *
。 std::vector<Shape>
不能存储Circle
。
每个动态容器中的每个对象始终是无条件的动态对象,其生命周期由容器管理。可配置的是内存分配策略,但这并不重要。请记住,C++ 将内存分配和对象创建作为两个不同的概念和职责范围分开。
【参考方案1】:
标准容器通过分配器对象分配内存,其类型作为模板参数传递。如果你没有传递其他任何东西,那就是std::allocator<T>
,它将使用new
来分配内存。
底线:您可以强制他们以几乎任何您想要的方式分配内存,但默认情况下它将来自免费存储。
如果你真的想要一个指针容器,容器将拥有指针对象(例如,当对象被销毁时会自动删除它们),你可能想看看 Boost Pointer Containers。
【讨论】:
【参考方案2】:使用指针来减少复制时间是真正的好处。想想所有可以通过它改进的向量操作 - 例如排序。
另一个真正的好处(如上面评论中所述)是这允许您使用多态性并将相关对象存储在同一向量中。标量对象(非指针)无法做到的事情。
您将数据存储在堆栈还是堆上并不会影响移动该对象的成本(嗯...确实如此,但通常可以忽略不计,并且与本次讨论无关)。
当您将指向对象的指针存储在 STL 向量中时,该向量不会取得对象的所有权。您仍然需要尽职调查并在不再需要它们时清理它们。
【讨论】:
【参考方案3】:[...] 而我现在认为它将它分配在堆上。这是正确的吗?
是的。如果将向量声明为:
std::vector<MyStruct*> v;
那么您基本上将指针存储在向量中,因此向量将分配内存来存储 指针,而不是指针指向的对象。所以当析构函数运行时,向量将释放它已经分配的内存,它不会释放指针本身的内存,即它不会释放存储在向量中的指针指向的内存。
但是,如果你这样声明:
std::vector<MyStruct> v;
然后你自己存储对象,所以向量将分配内存来存储对象,并在析构函数运行时释放它。
【讨论】:
【参考方案4】:当需要清理向量时,我会检查并删除 一切。我最近注意到这不像我一样有必要 以为是。
不要假设。如果向量中的指针指向动态分配的内存,那么您将需要删除该内存,因为向量不会为您执行此操作。
例如,如果您的代码属于该类型
MyStruct* pNewStruct = new MyStruct;
myVector.push_back(pNewStruct);
...
...
myVector.clear();
您有内存泄漏,因为您没有专门删除分配给添加到向量中的每个元素的内存。作为动态数组的一部分,向量释放了它在自身内部分配的内存,但这只是释放了指针数组,而不是它们指向的内存
【讨论】:
以上是关于C++ STL 内存管理:堆栈还是堆?的主要内容,如果未能解决你的问题,请参考以下文章