C++为什么创建一个新节点来删除堆栈上的节点是错误的

C++ why is creating a new node to delete a node on a stack wrong

本文关键字:节点 删除 堆栈 错误 新节点 创建 为什么 C++ 一个      更新时间:2023-10-16

我在课堂上学习单链表堆栈,我看到了这个stackoverflow页面,它给了我一些关于如何弹出节点的参考:

链表堆栈上的弹出功能

第一个答案使用以下代码弹出节点:

struct Node
{
int data;
Node *next;
};
int pop(Node *head)
{
while(head->next != NULL)
{
head = head->next;
}
int value;
Node *tmp;
tmp = new Node;
value = head->data;
tmp = head;
delete tmp;
return value;
}

第三个答案使用以下代码:

int pop( Node * &top )
{
int value = 0;
if ( top )
{
value = top->num;
Node *tmp = top;
top = top->next;
delete tmp;
}
return value;
}

现在,因为第一个答案,我最初这样写我的pop函数:

// Pop the top element off of the stack and return its value.
StackElement Stack::Pop()
{
assert (!Empty());
StackElement poppedData = tos->data;
Node *temp = new Node;
temp = tos;
tos = tos->next;
delete temp;   
return poppedData;
}

但是,我的老师说,创建一个新节点来删除以前的节点会导致内存泄漏。

最终,我重写了我的代码,以匹配样式二:

StackElement Stack::Pop()
{
assert (!Empty());
StackElement poppedData = tos->data;
Node *temp = tos;
tos = tos->next;
delete temp;   
return poppedData;
}

有人能向我解释为什么第一个实现是错误的吗?我很惊讶,当这个人把它发布在另一个stackoverflow问题上时,没有人对此发表评论。在我看来,我正在创建一个指向新节点(也称为新内存地址)的Node类型的指针temp,然后将该内存地址的值设置为堆栈内存地址顶部的值。我将栈顶移到下一个节点,然后删除我创建的这个临时节点,但因为我将其声明为一个新节点,它的值与旧栈顶的值相同,所以它实际上与该节点没有任何关系。旧的栈顶节点已从堆栈中删除,但内存未正确释放。这是正确的吗?

第一个答案是错误的。

tmp = new Node;
value = head->data;
tmp = head;
delete tmp;

这将删除您想要的head指针。但是该函数在tmp处创建新的内存分配,然后立即用值head覆盖指针。您现在已经丢失了指向已分配数据的指针。这是内存泄漏。