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