Нет, на самом деле вам необходимо это делать.
Однако почти весь код должен быть написан таким образом, чтобы данные удалялись, когда объект, которому они принадлежат, выходит за пределы области видимости, так что это произойдет (почти) неизбежно.
Другими словами, вы должны не обычно иметь что-то вроде:
// WARNING: bad code. Avoid this, or anything similar.
struct node {
int data;
struct node *next;
};
node *head = NULL;
int main() {
node *t = new node;
t->data = 1;
t->next = head;
head = t;
t = new node;
t->data = 2;
t->next = head;
head = t;
// here, do we bother to delete the two nodes or not?
};
Вместо этого вы обычно хотите создать класс, который инкапсулирует всю работу, и в своем деструкторе он освобождает всю память, которой он владеет:
class linked_list {
struct node {
int data;
node *next;
node(int data, node *next = NULL) : data(data), next(next) {}
} *root;
public:
void add(int data) {
root = new node(data, root);
}
~linked_list() {
node *prev = root;
for (node *temp = prev->next; temp!=NULL; temp=temp->next) {
delete prev;
prev = temp;
}
delete prev;
}
};
С таким классом действительно нет решения:
int main() {
linked_list x;
x.add(1);
x.add(2);
}
Когда выполнение достигает конца блока, в котором было определено x
, x
выходит за рамки и уничтожается. В процессе вызывается его деструктор, который удаляет узлы в связанном списке (конечно, по модулю любых ошибок в моем коде). Нет необходимости думать или заботиться о том, имеет ли смысл удалять узлы в этом случае, потому что это просто происходит автоматически каждый раз.
Обратите внимание, что я не говорю, что этот код (даже близко) на 100% идеален. С достаточно современным компилятором, чтобы поддерживать его, вы почти наверняка захотите, чтобы он был шаблоном, позволяющим хранить произвольный тип, и использовать unique_ptr
и make_unique
вместо необработанного указателя и необработанного new
. К сожалению, у меня нет другого выбора, кроме как пропустить их, так как я уверен, что Turbo C++ не поддерживает unique_ptr
, и сомневаюсь, что он также поддерживает шаблоны. Для реального использования это также должно включать в себя конструктор копирования и оператор присваивания, поэтому назначение и копирование связанных списков будет работать правильно (в нынешнем виде любой из них обычно приводит к проблемам, поскольку в конечном итоге он пытается уничтожить узлы в связанный список дважды).
Последнее замечание: конечно, обычно вам не следует писать собственный код связанного списка. Но когда/если у вас есть причина написать контейнер (или что-то подобное), он должен, так сказать, навести порядок в своем собственном беспорядке. Одной из сильных сторон C++ является детерминированное разрушение; используй это.
22.01.2014