Является ли рекурсивный деструктор для связанного списка, дерева и т. Д. Плохим?

В моем текущем учебном упражнении я изучаю связанные списки и деревья. Недавно я увидел предложение рекурсивно уничтожать структуры данных, заставляя каждый узел удалять своих дочерних / дочерних элементов. Однако почти во всех найденных мною примерах деструктор узла пуст, и некоторый управляющий класс обрабатывает уничтожение, используя ту или иную форму итерации и удаления. С точки зрения надежности и / или стилистики, есть ли что-то плохое в рекурсивном деструкторе?

Далее следует моя реализация моего понимания двух подходов.

Рекурсивное разрушение:

#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 узлов, я выхожу из строя. Итак, рекурсия явно представляет собой ошибку.

8
задан Jordan Gray 6 August 2011 в 07:28
поделиться