Написание деструктора LinkedList?

этот деструктор класса LinkedList? Они до сих пор меня смущают.

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

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

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

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

то, что меня беспокоит, достигает самого последнего узла. Условие "head;" должно проверить, что оно не равно null, но я не уверен, что оно будет работать.

любая помощь ценится.

6 ответов


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

ListNode* current = head;
while( current != 0 ) {
    ListNode* next = current->next;
    delete current;
    current = next;
}
head = 0;

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

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

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

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

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

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

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

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

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

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

то, что меня беспокоит, достигает самого последнего узла. Условие "head;" должно проверить, что оно не равно null, но я не уверен, что оно будет работа.

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

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


условие "head;" должно проверить, что оно не равно null, но я не уверен, что оно будет работать.

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

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

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


протестировано OK

деструктор для списка класса

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

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

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

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

List()::~List()
            {
                for( Link* ptr= Head; Head; Head= Head->next)
                {
                    delete ptr;
                }
            }