В моем текущем учебном упражнении я изучаю связанные списки и деревья. Недавно я увидел предложение рекурсивно уничтожать структуры данных, заставляя каждый узел удалять своих дочерних / дочерних элементов. Однако почти во всех найденных мною примерах деструктор узла пуст, и некоторый управляющий класс обрабатывает уничтожение, используя ту или иную форму итерации и удаления. С точки зрения надежности и / или стилистики, есть ли что-то плохое в рекурсивном деструкторе?
Далее следует моя реализация моего понимания двух подходов.
Рекурсивное разрушение:
#include <iostream>
struct Node {
static int count;
Node() : num_(count++), p_next_(0) {}
~Node() {
std::cout << "entering " << num_ << "\n";
delete p_next_;
std::cout << " leaving " << num_ << "\n";
}
const int num_;
Node* p_next_;
};
int Node::count = 0;
int main () {
Node* p_head = new Node();
p_head->p_next_ = new Node();
p_head->p_next_->p_next_ = new Node();
delete p_head;
return 0;
}
И вот мой взгляд на управление разрушением обработки классов. Предполагая, что я определил следующий DTOR для Node:
~Node() {std::cout << "Someone deleted " << num_ << "\n";}
я бы определил следующий управляющий класс LinkedList и последующий main
/* other stuff from above */
class LinkedList {
public:
LinkedList() : p_head_(new Node()) {
p_head_->p_next_ = new Node();
p_head_->p_next_->p_next_ = new Node();
}
~LinkedList() {
while(Node* p_prev = p_head_) {
p_head_ = p_head_->p_next_;
delete p_prev;
}
}
private:
Node* p_head_;
};
int main () {
LinkedList* p_list = new LinkedList();
delete p_list;
return 0;
}
. Предполагая, что я правильно читаю свои результаты, две мои реализации делают то же самое.
Что касается моего примера рекурсивного уничтожения, я думаю, что мне почти всегда будет нужен какой-то управляющий класс, содержащий копию головы, когда я решаю реальную проблему с кодом, но управляющему классу нужно только удалить голову / корневой узел, чтобы гарантировать разрушение всей структуры данных. Мне он кажется более элегантным, но у меня возникли проблемы с кодом, который я считал аккуратным.
Должен ли управляющий класс быть ответственным за правильное удаление всего? Или лучше, чтобы основная структура данных знала, как очистить себя? Есть ли какие-то неочевидные подводные камни?
Спасибо!
- Джордан
править: Мне пришла в голову мысль. Если у меня чрезвычайно длинная цепочка узлов, нужно ли мне беспокоиться о переполнении стека во время разрушения в первом примере, поскольку рекурсия играет роль?
edit2: Я полагаю, это должно было быть очевидным. А теперь я чувствую себя немного глупо. На моей машине, если у меня больше 64910 узлов, я выхожу из строя. Итак, рекурсия явно представляет собой ошибку.