如何从类列表中释放内存

时间:2010-04-05 16:55:23

标签: c++ memory

假设我有两个类创建了work和workItem。

        CWorker *work = new CWorker();
        CWorkItem *workItem = new CWorkItem();

工作类有一个公共列表m_WorkList,我将工作项添加到它。

work->m_WorkList.push_back(workItem);

如果我只是删除作品

if(work != NULL)
delete work;

我是否需要在析构函数中循环遍历列表,如下所示?有更好的方法吗?我可以使用clear吗?

while(m_WorkList.size())
{
    CWorkItem *workItem = m_WorkList.front();
    m_WorkList.pop_front();
    if(workItem)
        delete workItem;
}

6 个答案:

答案 0 :(得分:4)

是的,您需要delete每个项目。如果您拨打new N次,那么您还需要准确呼叫delete N次。批量删除项目没有捷径。

完成后,您需要在delete上致电work

如果要在堆上创建项目数组并分别一次性释放堆上的项目,则可以使用new[]delete[]。但在你的情况下,这不是你想要的。

如果您不想手动执行这些删除呼叫,可以查看boost::shared_ptr

答案 1 :(得分:3)

如其他回复中所述,您需要遍历列表并删除每个元素。如果你调用clear,它只会删除列表中没有指向对象的指针。

如果您需要包含所有权概念的列表,可以使用boost pointer container。它会确保在销毁列表时销毁您的对象

答案 2 :(得分:2)

假设您没有在其他地方维护workItems列表,那么是的,您需要在删除Worker本身之前单独删除它们(从而丢失引用)。如果Worker拥有唯一的列表,那么解构函数就像任何一个一样好(否则你需要在worker上调用delete之前“手动”删除每个workItem)

但是,如果workItems引用存在于其他位置,您可以选择适当的时间来删除它们,这可能是您删除Worker时可能会也可能不会。

答案 3 :(得分:2)

正如其他人所说,每delete你需要一个new。默认情况下,容器不会为您执行此操作。您不需要从列表中弹出项目。您可以创建一个仿函数来为您完成工作。对于无法使用tr1::shared_ptr或Boost的人来说,以下是常见做法。

struct deleter
{
    template <class T>
    void operator()(const T* ptr) const
    { 
        delete ptr;
    }
};

// Usage
std::for_each(work->m_WorkList.begin(), work->m_WorkList.end(), deleter());
delete work;

答案 4 :(得分:1)

这实际上取决于所有权,这是构建界面时需要决定的内容。假设你有一个方法:

CWorker::AddItem(CWorkItem *workItem)

您需要指定谁拥有内存,以及谁应该删除它。根据您尝试做的事情,调用者拥有它(如果项目应该在CWorkers之间常规共享)或者CWorker拥有它(如果每个CWorkItem属于一个CWorker)可能是有意义的。拥有它的人有责任删除它。

在前一种情况下,您可以将WorkItems作为shared_ptrs,指定在Workers之间共享所有权,并且您不需要手动删除。在后一种情况下,您还可以使用像ptr_vector这样的专用容器来避免手动删除的需要,但您还应该注意您正在控制内存的功能。

另外,作为一个注释,删除是空的安全,所以你不需要那些if语句,pop_back()比pop_front()更快

答案 5 :(得分:1)

使用boost shared_ptr(很快就会成为标准)

  typedef boost::shared_ptr<WorkItem> WorkItemPtr;
  ....
  std::list<WorkItemPtr> list;
  ...
  list.push_back(new WorkItem);

现在删除列表时,将删除WorkItems。您可以在代码中传递WorkItemPtrs,而不必担心它们。