代码之家  ›  专栏  ›  技术社区  ›  Jason Rowe

如何从类列表中释放内存

  •  2
  • Jason Rowe  · 技术社区  · 16 年前

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

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

    work类有一个公共列表m_work list,我将工作项添加到其中。

    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 回复  |  直到 16 年前
        1
  •  4
  •   Brian R. Bondy    16 年前

    是的,你需要 delete 每个项目。如果你打电话 new N次,然后你需要打电话 删除 也正好是N次。没有批量删除项目的快捷方式。

    当你做完了你需要打电话 删除 work .

    你可以使用 new[] delete[] 如果要在堆上创建一个项数组,并同时释放堆上的项。但对你来说这不是你想要的。

    你可以看看 boost::shared_ptr 如果不想手动执行这些删除调用。

        2
  •  3
  •   chub    16 年前

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

    如果您需要一个包含所有权概念的列表,您可以使用 boost pointer container . 它将确保当您销毁列表时销毁您的对象

        3
  •  2
  •   Dusty    16 年前

    假设您没有在其他地方维护工作项列表,那么是的,您需要在删除工作项本身之前逐个删除它们(从而丢失引用)。如果工人持有唯一的列表,那么解构器就和任何解构器一样好(否则,在调用工人本身的delete之前,您需要“手动”删除每个工作项)

    但是,如果工作项引用存在于其他地方,则可以选择适当的时间删除它们,这可能是删除工作项时的时间,也可能不是。

        4
  •  2
  •   Michael Kristofik    16 年前

    正如其他人所说,你需要一个 delete 每一个 new . 默认情况下,容器不会为您执行此操作。不过,你不需要把这些项目从列表中弹出。你可以创建一个函子为你做这项工作。以下是不能使用的人的常见做法 tr1::shared_ptr 或助推。

    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;
    
        5
  •  1
  •   Todd Gardner    16 年前

    它实际上取决于所有权,这是您在构建接口时需要决定的。假设你有一个方法:

    CWorker::AddItem(CWorkItem *workItem)
    

    您需要指定谁拥有内存,因此谁应该删除它。取决于您尝试做什么,呼叫方拥有它(比如项目是否应该在cWorkers之间定期共享)或cWorker拥有它(如果每个cWorkitem属于单个cWorker)都是有意义的。不管谁拥有它都要负责删除它。

    在前一种情况下,您可以将工作项作为共享项,以指定工作人员之间共享的所有权,而不需要手动删除。在后一种情况下,还可以使用 ptr_vector 为了避免手动删除的需要,您还应该注意正在控制内存的函数。

    另外,请注意,delete是空安全的,因此不需要那些if语句,而且pop_back()比pop_front()更快

        6
  •  1
  •   pm100    16 年前

    使用boost shared_ptr(这将很快成为标准)

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

    现在当列表被删除时,工作项将被删除。您可以在代码中传递工作诱惑者,而不必担心它们。