Как написать деструктор для класса, в котором одно из полей -- структура?

Рейтинг: 2Ответов: 2Опубликовано: 12.04.2015

На StackOverflow задавался вопрос о том как написать простой связный список на C++. Там же был дан ответ, в котором создается структура, как приватное поле класса. Вот код, который был приведен там:

class LinkedList{
    // Struct inside the class LinkedList
    // This is one node which is not needed by the caller. It is just
    // for internal work.
    struct Node {
        int x;
        Node *next;
    };

// public member
public:
    // constructor
    LinkedList(){
        head = NULL; // set head to NULL
    }

    // This prepends a new value at the beginning of the list
    void addValue(int val){
        Node *n = new Node();   // create new Node
        n->x = val;             // set value
        n->next = head;         // make the node point to the next node.
                                //  If the list is empty, this is NULL, so the end of the list --> OK
        head = n;               // last but not least, make the head point at the new node.
    }

    // returns the first element in the list and deletes the Node.
    // caution, no error-checking here!
    int popValue(){
        Node *n = head;
        int ret = n->x;

        head = head->next;
        delete n;
        return ret;
    }

// private member
private:
    Node *head; // this is the private member variable. It is just a pointer to the first Node
};

Как написать деструктор для этого класса?

Ответы

▲ 2Принят

Вставьте конструктор и деструктор в Node:

struct Node {
   Node() : next(NULL) {}
   ~Node() {if(next) delete next;}

   int x;
   Node *next;
};

В классе тоже самое, добавьте в деструктор строку:

if(head) delete head;

Тогда ноды будут удаляться при уничтожении объекта класса автоматом и рекурсивно.

Update:

int popValue(){
   Node *n = head;
   int ret = n->x;

   head = head->next;
   n->next = NULL;
   delete n;
   return ret;
}

Update 2 (полный листинг):

#include <iostream>
using namespace std;

class LinkedList{
    // Struct inside the class LinkedList
    // This is one node which is not needed by the caller. It is just
    // for internal work.
    struct Node {
       Node() : next(NULL) {}
       ~Node() {if(next) delete next;}

       int x;
       Node *next;
    };

// public member
public:
    // constructor
    LinkedList(){
        head = NULL; // set head to NULL
    }

    ~LinkedList() {
        if(head)
            delete head;   
    }

    // This prepends a new value at the beginning of the list
    void addValue(int val){
        Node *n = new Node();   // create new Node
        n->x = val;             // set value
        n->next = head;         // make the node point to the next node.
                                //  If the list is empty, this is NULL, so the end of the list --> OK
        head = n;               // last but not least, make the head point at the new node.
    }

    // returns the first element in the list and deletes the Node.
    // caution, no error-checking here!
    int popValue(){
       Node *n = head;
       int ret = n->x;

       head = head->next;
       n->next = NULL;
       delete n;
       return ret;
    }

// private member
private:
    Node *head; // this is the private member variable. It is just a pointer to the first Node
};

int main() {
    LinkedList list;

    list.addValue(5);
    list.addValue(10);
    list.addValue(20);

    cout << list.popValue() << endl;
    cout << list.popValue() << endl;
    cout << list.popValue() << endl;
    // because there is no error checking in popValue(), the following
    // is undefined behavior. Probably the program will crash, because
    // there are no more values in the list.
    // cout << list.popValue() << endl;
    return 0;
}
▲ 3

Во первых там вовсе не структура, а указатель на неё. Это две большие разницы.

Во вторых не ясно что вы собственно собрались уничтожать если сам класс является просто оберткой для головы списка.

Думаю что проще определить в нем метод для удаления всего списка clearList() с явным циклическим проходом по всем узлам и просто вызывать его в деструкторе.

P.S. Стоит иметь в виду что этот класс совершенно негоден для реального применения. Он явно зависит от типа данных элемента списка, в нем нет никакой обработки ошибок, конструкторов, полезных методов для итерации по списку. Там даже удаления произвольного элемента нет. На практике проще использовать std::list