【问题标题】:C++ STL Memory Management: Stack or Heap?C++ STL 内存管理:堆栈还是堆?
【发布时间】:2012-07-28 09:49:25
【问题描述】:

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

std::vector<MyStruct*> 

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

【问题讨论】:

  • std::vector&lt;Shape *&gt; 可以存储Circle *std::vector&lt;Shape&gt; 不能存储Circle
  • 每个动态容器中的每个对象始终是无条件的动态对象,其生命周期由容器管理。可配置的是内存分配策略,但这并不重要。请记住,C++ 将内存分配和对象创建作为两个不同的概念和职责范围分开。

标签: c++ memory-management stl


【解决方案1】:

标准容器通过分配器对象分配内存,其类型作为模板参数传递。如果你没有传递其他任何东西,那就是std::allocator&lt;T&gt;,它将使用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();
        

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-10-10
          • 1970-01-01
          • 2012-03-07
          • 2017-04-28
          • 1970-01-01
          • 2011-09-16
          • 2010-11-13
          • 1970-01-01
          相关资源
          最近更新 更多