Написание деструктора 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;
}
}