我有一个我必须为我的Uni类做的数据结构项目,它实现了一个带有链表的堆栈;简单的东西。我们在代码方面得到了一些帮助,向我们展示了实现这种结构的正确方法。
Stack class:
class Stack
{
public:
Stack(void)
{
top = NULL; // Initialises defualt top node pointer.
}
~Stack(void)
{
while (NodePop() != NULL){}
}
void Push(int value) // Pushes a new node onto the stack.
{
Node* temp = new Node(value, top); // Creates a temporary node with a value and makes it
// point to the top node as the next node in the stack.
top = temp; // Temporary node becomes the top node in the stack.
}
Node* NodePop(void)
{
/* Remove top node from the stack */
Node* temp = top; // Creates a temporary node to return, sets it to top node.
if (top != NULL) top = top->getNext(); // Points the stacks top node to the next node in the list.
return temp; // Returns a pointer to the popped node still in the heap.
}
int Pop(void) // Pops the top node off of the stack. Returns the nodes value.
{
Node* temp = NodePop();
int valueReturn = 0;
/* Sets the return value */
if (temp != NULL)
{
valueReturn = temp->getVal(); // Set return value to the nodes value if there is a node left.
}
else
{
throw "Stack Empty"; // Throws exception if temp is NULL and stack is empty.
}
delete temp; // Deletes the node entirely from the heap.
return valueReturn;
}
private:
Node* top;
};
节点类:
class Node
{
public:
Node(int value, Node* nextptr = NULL, Node* prevptr = NULL, int currentpriority = 0)
{
/* Set initial variables for the node at creation */
this->value = value;
this->next = nextptr;
this->prev = prevptr;
this->priority = currentpriority;
}
// bunch of getters and setters...
private:
Node* next; // Pointer to the next node.
Node* prev; // Pointer to the previous node.
int priority; // Stores the node priority as a number 0-9.
int value; // Stores the node value for printing.
};
我们不能改变任何类结构(我的烦恼,NodePop()应该是私有的,但是w / e)。
所以这里NodePop()基本上从列表中删除了顶级节点,但是没有删除它;它从链表中删除对它的所有引用,但它从不从堆中删除它,它只从Pop()中的堆中删除。一切都很好(除了能够公开调用NodePop(),但同样,我不允许将其设为私有)。但是当我调用析构函数时,必须使用NodePop(),而不是Pop()。
这是否意味着当NodePop()从析构函数运行时,节点永远不会从堆中删除?
如果是这样,我将如何删除它们,因为如果我在while,do-while或if语句中有它,那么它将会运行nodePop()所以总会有一个节点被取消删除吗
答案 0 :(得分:3)
查看有问题的代码
~Stack(void)
{
while (NodePop() != NULL){}
}
Node* NodePop(void)
{
/* Remove top node from the stack */
Node* temp = top; // Creates a temporary node to return, sets it to top node.
if (top != NULL) top = top->getNext(); // Points the stacks top node to the next node in the list.
return temp; // Returns a pointer to the popped node still in the heap.
}
你的析构函数调用NodePop()直到该函数返回NULL。让我们看看NodePop()的作用。代码中的注释声称它Creates a temporary node to return
这不是真的。它创建一个指向Node(Node *)的指针,并将该指针设置为指向top
所在的相同位置。如果top
不为空,则会将top
设置为指向顶部的下一个节点。返回temp
,其中是指向最初节点的指针。
在任何时候你都没有释放与任何节点相关的内存,所以是的是内存泄漏。
您可以通过删除在析构函数中遇到的非NULL的每个Node *来修复泄漏。
答案 1 :(得分:0)
实际上,节点不会被删除,而且这段代码会泄漏。您可以使用Valgrind等工具验证这一点。
我会将while
更改为while (Node *N = NodePop()) delete N;
仅供参考,这段代码绝对不是惯用的C ++ 11。它的写作基本上写得不好C,我希望能找到更多的错误。你的老师应该在手腕上打一巴掌,就像这样呈现C ++ 11: - )