假设我有两个类创建了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;
}
答案 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,而不必担心它们。