我在IntList
实现中向push_back
个节点提供了一小段代码。我的问题是*pnode
是否导致内存泄漏,或者我是否需要在最后删除它。
void IntList::push_back(int data){
if (first){
IntNode *pNode = first;
while(pNode->next!=0){pNode = pNode->next;}
pNode->next = new IntNode(data);
} else
first = new IntNode(data);
}
答案 0 :(得分:1)
不,您不需要在delete
上致电pNode
。您只能在使用delete
创建的内容上调用new
。使用现在的代码pNode
是一个堆栈对象,当它在函数末尾超出范围时将自动销毁。
答案 1 :(得分:0)
您必须删除最终使用new创建的IntNode,可能是在容器的析构函数和pop_back函数中。 pNode本身(指针)在堆栈上分配,而不是new,因此不需要删除。
答案 2 :(得分:0)
您不需要删除pNode
。而且,在这种特殊情况下你无法做到这一点。
在使用new
创建内容后,您必须delete
一次 - 一旦您永远不会使用它。
使用delete
删除对象后,尝试读取其内容为undefined behavior。指针通常是c++中产生错误最多的部分之一,所以你试图更好地理解它是件好事。
你可以用这种方式想象自己:你可以用new
买房子(房子是一块记忆)。它会返回你的地址。它现在是你的房子,可以随心所欲。您也可以使用delete
进行销售。在此之前,你可以给你的朋友你的家庭住址,以便他们可以来找你。分配地址,导致复制它(例如IntNode *pNode = first;
)。但是,你仍然只有一所房子。因此,无论您复制家庭住址多少次,您只能出售一次房屋。
我建议使用智能指针(例如std::unique_ptr
),但我认为这个程序用于学习编程,所以不要这样做;)
答案 3 :(得分:0)
您需要在每个从列表中删除节点的函数上删除节点,而不是在插入时删除节点。不这样做会导致泄漏。
如果在破坏对象时仍有分配的节点,则需要迭代整个列表以删除所有节点。不这样做也会导致泄密。
我认为这是一项大学任务,因为有数百万经过实战考验的链表实施。
如果你在所有函数上保持最新的尾节点,你会做得更好,所以你可以避免迭代整个列表以在尾部插入一个节点。
答案 4 :(得分:0)
您显示的代码不足以判断您是否泄漏了内存。您显示负责分配的例程,但不显示您执行重新分配的代码。
如果你没有任何代码执行解除分配,那么是的,显然是泄漏。 C ++不执行自动垃圾收集,因为您可能习惯于其他语言。
您正在使用裸new
,所以即使您确实有其他代码试图进行重新分配,也会有不正确的更改。
在C ++中,您通常不应该直接使用new
运算符,而应该学会使用RAII来处理资源。 IntList可能使用拥有原始指针,这是另一个要避免的事情。在这种情况下,您可能应该使用unique_ptr<IntNode>
。例如:
struct IntList {
struct IntNode {
unique_ptr<IntNode> next;
int data;
IntNode(int data) : data(data) {}
};
unique_ptr<IntNode> first;
// returns a reference to the null pointer which terminates the linked list
unique_ptr<IntNode> &get_tail() {
if (!first) {
return first;
}
IntNode *pNode = first.get(); // pNode is a non-owning pointer
while (pNode->next) {
pNode = pNode->next.get();
}
return pNode->next;
}
void push_back(int data) {
get_tail() = make_unique<IntNode>(data);
}
};
上述代码确实存在问题,但问题与内存泄漏无关。销毁列表后,first
会自动销毁,会自动销毁first->next
,依此类推。可以将如此多的元素插入到列表中,这种破坏链条会破坏&#39;函数堆栈,导致未定义的行为。
可以使用IntList析构函数修复问题,该析构函数以相反的顺序销毁节点:
IntList::~IntList() {
while (first) {
unique_ptr<IntNode> tmp = std::move(first);
first = std::move(tmp->next);
}
}
有趣的是,这是Rule of Three的例外示例。