Действительно ли это - допустимый деструктор LinkedList? Я - все еще вид запутанных ими.
Я хочу удостовериться, что я понимаю это правильно.
LinkedList::~LinkedList()
{
ListNode *ptr;
for (ptr = head; head; ptr = head)
{
head = head->next
delete ptr;
}
}
Таким образом в начале цикла, указатель ptr установлен содержать адрес головы, первого узла в списке. голова тогда установлена на следующий объект, который станет началом списка, как только это первое удаление происходит. ptr удален и первый узел - также. С первым повторением цикла указатель установлен направиться снова.
Вещь, которая касается меня, достигает самого последнего узла. Условие "голова"; должен проверить, что это не является пустым, но я не уверен, будет ли это работать.
Любая справка ценится.
Почему бы не сделать это намного проще - с помощью элегантного while
-петли вместо того, чтобы пытаться тщательно анализировать, правильна ли эта перекомпилированная for
-петля?
ListNode* current = head;
while( current != 0 ) {
ListNode* next = current->next;
delete current;
current = next;
}
head = 0;
Вы можете запустить его через отладчик, или вы можете запустить его через этот бит программного обеспечения внутри вашего черепа - оба покажут вам, что он работает нормально. Например, давайте начнем со списка:
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 просто потому, что вы выйдете из тела цикла до этой точки (или даже не вошли в тело, если список пуст. ).
Любое другое значение указателя будет рассматриваться как истина, и вы войдете или продолжите тело цикла.
Условие «голова»; должен проверить, что он не равен нулю, но я не уверен, что это сработает.
Да, «head» само по себе то же самое, что «head! = Null», но зачем использовать бессмысленные ярлыки для набора текста, если даже вы находите это запутанным? Осталось всего 6 нажатий клавиш (и генерируется идентичный машинный код), поэтому выбирайте длинную форму.
Кроме того, ваш код немного сложнее, чем необходимо, потому что вы используете конструкцию for ()
. Почему бы не использовать while ()
? Ваш код будет намного чище.
Наконец, я понимаю, что вы делаете это в качестве обучающего упражнения, но имейте в виду, что list <> находится в стандартной библиотеке --- Связанные списки официально являются «Решенной проблемой».
Ваш код может быть правильным, попробуйте запустить его, например, valgrind и посмотрите, что там написано. Однако я бы написал это так:
for (ListNode *current = head, *next; current; current = next) {
next = current->next;
free(current);
}