用于指向其值的双向链表的析构函数

时间:2012-12-10 01:38:05

标签: c++ memory linked-list

假设我有一个由类

定义的双向链表
    class list
    {
        /*...*/

    private:
        struct node
        {
           node* prev;
           node* next;
           int* value;
        }

        node* first; //NULL if none
        node* last; //NULL if none

        /*...*/
    }

如果我想为此列表创建析构函数,我是否必须明确删除该值?

list::~list()
{
    node* move = first;
    while(first)
    {
        first = move->next;
        delete move;
        move = first;
    }
}

上述工作是否可以确保没有内存泄露?或者我必须这样做:

list::~list()
{
    node* move = first;
    while(first)
    {
        first = move->next;
        delete move->value;
        delete move->prev;
        delete move;
        move = first;
    }
}

我很困惑如何在这种情况下确保没有内存泄露。我如何具体处理节点中的指针?如果我删除move会自动处理这些吗?

3 个答案:

答案 0 :(得分:1)

您需要将每个new与一个delete配对。也就是说,您可能不希望delete prev(此节点已被删除),但您想要delete value。好吧,我将value嵌入到对象中,而不是指向它:

struct node
{
     node* prev;
     node* next;
     int   value;
};

如果value绝对需要成为指针,我会使用std::unique_ptr<int>(或者,如果您需要使用C ++ 2003,则为std::auto_ptr<int>)。

答案 1 :(得分:1)

对于每个成功的new表达式,请在该对象上为delete完全>

对于每个成功的new[]表达式,请在该对象上为delete[]完全>

这意味着你的清理功能都没有问题:

  • 第一个功能会忘记delete value,这意味着内存泄漏

  • 通过删除列表中每个节点的movemove->prev,第二个功能可能会删除大多数节点两次,即未定义行为。 / p>

为避免第一个函数的内存泄漏,只需直接存储整数,而不是动态分配它。

答案 2 :(得分:1)

是否必须通过value成员删除内存指针 - 只有您可以知道。这是一个关于内存所有权的问题,一个关于你的设计的问题。如果列表拥有 value成员指向的数据内存,那么您必须在列表析构函数中删除它(即当列表终止时,它拥有的数据随之消失)。

如果列表不拥有value内存,那么您不应该删除它。同样,只有你可以回答你的列表是否应该拥有value内存的问题。这是你的意图。

现在,对于node对象占用的内存,它显然属于列表,因此必须在析构函数中小心地释放它。您的destcructor的第一个版本接近正确(第二个版本根本没有意义),除了它以略微混淆的方式编写。这应该足够了

list::~list()
{
  while (first)
  {
    node *move = first;
    first = first->next;
    delete move;
  }
}

(同样,如果您必须删除value,则应在delete move->value之前将delete move添加到您的周期中。)

P.S。一旦得到这个,您可能想要查看各种智能指针类,它们允许您明确表达内存所有权关系,从而使编译器知道它们。如果使用得当,它们将使内存管理几乎自动化。