Написание деструктора LinkedList? - PullRequest
12 голосов
/ 15 февраля 2010

Это действительный деструктор LinkedList? Я все еще смущен ими.

Я хочу убедиться, что правильно понимаю.

 LinkedList::~LinkedList()
 {
   ListNode *ptr;

   for (ptr = head; head; ptr = head)
   {
     head = head->next
     delete ptr;
   }
}

Таким образом, в начале цикла указатель ptr устанавливается для хранения адреса заголовка, первого узла в списке. Затем заголовок устанавливается на следующий элемент, который станет началом списка после первого удаления. PTR удаляется, как и первый узел. На первой итерации цикла указатель снова устанавливается в заголовок.

Меня беспокоит то, что я достиг последнего узла. Состояние "голова" следует проверить, что оно не равно нулю, но я не уверен, будет ли оно работать.

Любая помощь приветствуется.

Ответы [ 6 ]

15 голосов
/ 15 февраля 2010

Почему бы не сделать это намного проще - с элегантным while -циклом, вместо того, чтобы пытаться тщательно проанализировать, является ли этот перекомпилированный for -петл правильным?

ListNode* current = head;
while( current != 0 ) {
    ListNode* next = current->next;
    delete current;
    current = next;
}
head = 0;
5 голосов
/ 15 февраля 2010

Вы можете запустить его через отладчик или же запустить через эту часть программного обеспечения внутри вашего черепа - оба покажут вам, что он работает нормально. Например, давайте начнем со списка:

head(47) -> [47]single_node -> [NULL]end-of-list.

Выполнение этого списка через ваши заявления:

  • ptr = head устанавливает ptr на 47.
  • head не равен нулю, поэтому введите цикл.
  • head = head->next устанавливает head в NULL.
  • delete ptr удалит single_node.
  • ptr = head устанавливает ptr в NULL.
  • head теперь равно NULL (0), поэтому выйдите из цикла.

Итак, вы удалили единственную запись в списке, и head теперь имеет значение NULL. Это все, что вам нужно сделать.

Вы можете сделать аналогичную вещь с более длинным списком или пустым списком, вы обнаружите, что все в порядке (нет реальной разницы между списком из одного элемента и списком из пятидесяти элементов).

Кроме того, я не большой поклонник того, чтобы относиться к указателям как к логическим значениям - я бы лучше написал это примерно так:

for (ptr = head; head != NULL; ptr = head)

По моему мнению, это делает код лучше читаемым, и вы действительно не жертвуете производительностью (если у вас нет мертвого компилятора). Но это дело вкуса.

Ваш комментарий:

Меня беспокоит то, что я достиг последнего узла. Состояние "голова" следует проверить, что оно не равно нулю, но я не уверен, будет ли оно работать.

Это будет работать. Нулевое значение будет рассматриваться как ложное, поэтому вы обнаружите, что никогда не разыменовываете head-> next, когда head равно NULL просто потому, что вы вышли из тела цикла до этой точки (или даже не вошли в тело, если список пуст ).

Любое другое значение указателя будет считаться истиной, и вы введете или продолжите тело цикла.

3 голосов
/ 15 февраля 2010

Условие "голова"; следует проверить, что это не ноль, но я не уверен, будет ли это работать.

Да, «голова» сама по себе такая же, как и «голова! = Ноль» - но зачем использовать бессмысленное сочетание клавиш, если даже вы находите это непонятным? Это всего лишь 6 нажатий клавиш (и генерирует идентичный машинный код), так что перейдите на длинную форму.

Кроме того, ваш код немного сложнее, чем необходимо, потому что вы используете конструкцию for(). Почему бы не использовать while()? Ваш код будет намного чище.

Наконец, я понимаю, что вы делаете это как учебное упражнение, но имейте в виду, что список <> находится в стандартной библиотеке - официальные списки связанных списков являются «Решенной проблемой».

2 голосов
/ 10 января 2014

Проверено ОК

Деструктор для класса List

List::~List()
{
    Node *n = this->front, *current = NULL; //initialization part

    while(n)                               //start cleanup of nodes of the list
    {
        current = n;
        n=n->next;
        delete(current);
    }

    front = end = NULL;
}
0 голосов
/ 23 мая 2017

Это лучший подход для освобождения / удаления памяти с использованием деструктора Linked-List.

List()::~List()
            {
                for( Link* ptr= Head; Head; Head= Head->next)
                {
                    delete ptr;
                }
            }
0 голосов
/ 15 февраля 2010

Ваш код может быть верным, попробуйте запустить его, например, с помощью valgrind и посмотри, что там написано. Однако я бы написал так:

for (ListNode *current = head, *next; current; current = next) {
    next = current->next;
    free(current);
}
...