struct Node {
int value;
Node* next;
~Node() {
delete next;
}
};
Node* deleteList(Node* p) {
if(p == nullptr) return nullptr;
Node* pNext = p->next;
delete p;
return deleteList(pNext);
}
编译器说了一些关于访问不良的信息。 我试图设置断点来调试它。如果链表是[3,2,1],它首先删除3,然后删除2和1,然后跳回到2,然后遇到异常。 有人能告诉我这是什么问题吗?
答案 0 :(得分:3)
Node结构的析构函数已经在“next”上调用delete。因此,它转到“next”并调用它的析构函数,依此类推。然后,只需调用p
(其中p是节点*)即可删除链接列表中delete p;
后面的所有节点。
我建议你摆脱Node的析构函数,以防止发生链破坏。
struct Node {
int value;
Node* next;
};
作为旁注,虽然我不知道你的其余代码,但我没有看到为什么deleteList(Node * p)应该返回一个Node *的原因(因为它总是nullptr,没有意思结果返回)。
void deleteList(Node* p)
{
if(p == nullptr) return;
Node* pNext = p->next;
delete p;
deleteList(pNext);
}
答案 1 :(得分:2)
我会猜测您在已删除的实例上多次调用delete
。当你调用delete p;
时,p
的析构函数被调用,它正在删除列表中的下一个节点。然后递归调用deleteList
,向它传递刚刚被p
的析构函数删除的节点,使你指向的指针无效。
您需要做的是确定Node
是否拥有列表中跟随它的Node
(即,是否负责清理它),或者某些外部代码是否需要注意那个。你不能两者兼顾。
编辑:
顺便说一句,你真正想要的不是有一个递归删除函数,而是一个deleteList
函数中的循环。有点像...
struct Node {
int value;
Node* next;
};
// Loop in the function; recursion not required, and no return value.
void delete_list(Node* n)
{
Node* tmp;
while (nullptr != n) {
tmp = n->next;
delete n;
n = tmp;
}
}
在这种情况下,Node
实例不拥有其兄弟Node
(Node.next),并且不负责解除分配;这取决于delete_list
函数。
答案 2 :(得分:2)
如果链接列表为:[3, 2, 1]
,则当您致电deleteList
时,会发生以下情况:
p = 3
,pNext = 2
,3
被delete p;
删除然后调用了析构函数,因此delete next
会删除2
和递归1
。
然后在delete p
函数deleteList
之后,再次调用deleteList(pNext)
,所以这次:p = 2
,pNext = 1
,因为{{1在上一步中已经删除了,当你再次调用2
时它会损坏。
请删除delete p
中的delete next;
。
实际上我没有看到为什么应该使用~Node()
的原因,因为它总会返回deleteList
并删除所有节点。那么为什么不删除nullptr
函数,并将deleteList
保留在delete next;
中。您可以直接删除创建的~Node()
对象。
当然,执行此任务的最佳方式是:Node
。
答案 3 :(得分:1)
从delete next;
的析构函数中删除行Node
。
答案 4 :(得分:0)
我认为你可能有两种选择。
首先,正如R Sahu所说,删除析构函数中的delete next
。
struct Node {
int value;
Node* next;
};
Node* deleteList(Node* p) {
if(p == nullptr) return nullptr;
Node* pNext = p->next;
delete p;
return deleteList(pNext);
}
第二,只需删除deleteList
中链接的头节点,但不能递归删除节点。
struct Node {
int value;
Node* next;
Node() : value(0), next(nullptr)
{}
~Node() {
if (next != nullptr)
{
delete next;
}
}
};
Node* deleteList(Node* p) {
if (p != nullptr)
{
delete p;
}
return nullptr; // in fact your code always return nullptr. so it just return nullptr here.
}