2

クラスによって定義された双方向にリンクされたリストがあるとします

    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;
    }
}

この場合、メモリがリークしないようにする方法について混乱しています。ノード内のポインターを具体的にどのように処理すればよいですか? 移動を削除すると、これらは自動的に処理されますか?

4

3 に答える 3

1

Whether you have to delete the memory pointer by the value member - only you can know. It is a question of memory ownership, a question of your design. If the list owns the data memory pointed by the value members, then you have to delete it in the list destructor (i.e. when the list dies, the data it owned dies with it).

If the list does not own the value memory, then you are not supposed to delete it. Again, only you can answer the question of whether your list is supposed to own the value memory. It is a matter of your intent.

Now, as for the memory occupied by node objects, it is obviously owned by the list, so it has to be carefully deallocated in the destructor. The first version of your destcructor is close to being correct (the second makes no sense at all), except that it written in a slightly obfuscated fashion. This should be sufficient

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

(Again, if you have to delete value, then delete move->value should be added to your cycle before delete move.)

P.S. Once you get this, you might want to look into various smart pointer classes, which allow you to explicitly express memory ownership relationsips, thus making them known to the compiler. When used properly, they will make memory management almost automatic.

于 2012-12-10T01:49:04.367 に答える
1

For each successful new expression, call delete exactly once on that object.

For each successful new[] expression, call delete[] exactly once on that object.

That means that neither of your cleanup functions are OK:

  • The first function forgets to delete the value, which means a memory leak.

  • The second function, by deleting both move and move->prev at each node in the list, risks deleting most nodes twice, which is Undefined Behavior.

To avoid the memory leak for the first function, simply store the integer directly instead of allocating it dynamically.

于 2012-12-10T01:45:17.060 に答える
1

newそれぞれを正確に 1 つとペアにする必要がありますdelete。つまり、おそらくしたくないdelete prev(このノードは既に削除されています) でも、したいということdelete valueです。さて、私はそれを指すのではなくvalue、オブジェクトに埋め込みます:

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

value絶対にポインターである必要がある場合は、a std::unique_ptr<int>(または、C++ 2003 を使用する必要がある場合は a std::auto_ptr<int>) を使用します。

于 2012-12-10T01:42:12.880 に答える