C++ 递归删除链表会导致堆栈溢出吗?

C++ 递归删除链表会导致堆栈溢出吗?,c++,pointers,recursion,memory-management,linked-list,C++,Pointers,Recursion,Memory Management,Linked List,我有一个由节点对象构建的链表: class Node { public: Node(string data); Node* GetNext() const; void SetNext(Node* nextNode); ~Node(); private: string data; Node* next; }; 析构函数的定义如下: Node::~Node() { delete next; } 其中应该在h

我有一个由
节点
对象构建的链表:

class Node {
   public:
      Node(string data);
      Node* GetNext() const;
      void SetNext(Node* nextNode);
      ~Node();
   private:
      string data;
      Node* next;
};
析构函数的定义如下:

Node::~Node() {
   delete next;
}
其中应该在head
节点上调用析构函数


我的问题是:像这样删除单链表会不会导致大列表上的堆栈溢出(它在小列表(即小于10个大小的列表)上工作正常)。如果是这样的话,使用迭代解决方案会更好吗

while (head->GetNext() != 0) {
   Node* temp = head->GetNext();
   head->SetNext(temp->GetNext());
   delete temp;
}
delete head;

如果没有为
节点定义构造函数

堆栈大小始终限制函数上递归调用的深度。即使使用析构函数(以及其他没有参数的函数),也必须保留该函数调用的返回地址(析构函数无论如何都会将
this
指针作为隐式参数)

因此,从
节点的某个上限开始,堆栈将溢出,是的


迭代方法在这方面更加稳健。

解决方案的问题是,每次调用
~Node()
方法时,堆栈帧都在堆栈上不断累积。以3个
节点
对象为例,从开始,比如说
0x01
。删除它们会有以下堆栈帧回溯(我假设每个节点对象包含1位信息,这不是真的,但会使列表更整洁):

因此,对于一百万个
节点
对象,在第一个堆栈帧完成之前,您将拥有一百万个堆栈帧。每个堆栈帧都会占用堆栈上的空间,因此,是的,您可能会耗尽堆栈空间

迭代解决方案不会遇到这个问题,因为对于每个迭代,删除
节点
的调用在下一个
节点
删除例程运行之前完成。这意味着在每次迭代期间,堆栈上只有一个函数调用(加上或减去完成该函数调用所需的数量,但特别是,它不是递归的)


除了这个问题之外,还有一个问题被提出了,那就是你没有任何方法来删除一个
节点
对象。您可以删除整个列表或部分列表。想象一下,如果客户机在上一个示例中引用了
节点(0x02)
,并调用
删除节点
,会发生什么情况。在这种情况下,
Node(0x02)
Node(0x03)
将被删除,但是
Node(0x01)
仍将有一个指向
Node(0x02)
的内存指针的引用。取消对此的引用将导致崩溃

我没有得到这些奇怪的链表实现,在链表中,节点正在破坏自身和链中的任何其他节点。如果我想从列表中删除一个节点,该怎么办?更好的选择是创建一个链表类,其中成员是节点指针,链表类根据需要删除和分配节点。节点类不应该有任何用户定义的析构函数。它很容易导致堆栈溢出。在你的链表上抛出一百万个节点并尝试一下。“这样删除单链表会导致大列表上的堆栈溢出吗?”。当然,您自己测试这个应该很容易迭代版本更适合堆栈溢出,因为它不是递归的。为什么不在具有
节点*头的
类列表
中实现销毁呢?我们这里讨论的是动态分配的指针,所以从技术上讲,我认为我们讨论的是堆溢出。
 (0) Node (0x01): ~Node
 (1) Node (0x02): ~Node
 (2) Node (0x03): ~Node