2

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

std::vector<MyStruct*> 

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

4

4 回答 4

8

标准容器通过分配器对象分配内存,其类型作为模板参数传递。如果你没有传递任何其他东西,那就是std::allocator<T>,它将用于new分配内存。

底线:您可以强制他们以几乎任何您想要的方式分配内存,但默认情况下它将来自免费存储。

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

于 2012-07-28T09:56:55.660 回答
3

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

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

无论您将数据存储在堆栈还是堆上,都不会影响移动该对象的成本(嗯......确实如此,但通常可以忽略不计,并且与本讨论无关)。

当您将指向对象的指针存储在 STL 向量中时,该向量不会获得您的对象的所有权。您仍然需要进行尽职调查并在不再需要它们时进行清理。

于 2012-07-28T09:54:40.890 回答
3

[...] 而我现在认为它将它分配在堆上。它是否正确?

是的。如果将向量声明为:

std::vector<MyStruct*> v;

那么您基本上将指针存储在向量中,因此向量将分配内存来存储指针,而不是指针指向的对象。所以当析构函数运行时,向量将释放它已经分配的内存,它不会释放指针本身的内存,即它不会释放存储在向量中的指针指向的内存。

但是,如果您声明:

std::vector<MyStruct> v;

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

于 2012-07-28T09:56:13.690 回答
2

当需要清理向量时,我会检查并删除所有内容。我最近注意到这并不像我想象的那样是必要的。

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

例如,如果您的代码属于

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

 ...
 ...

 myVector.clear();

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

于 2012-07-28T09:52:27.137 回答