我查看了许多单链表的例子,它作为堆栈工作。它们有以下共同点:它们总是在pop()函数中的弹出项目上使用 free ,例如:
struct Node
{
struct Node *Next;
}*Head;
void pop()
{
struct Node *cur_ptr=Head;
....
Head = Head->Next;
// do something with cur_ptr
free(cur_ptr);
....
}
我是否总是需要使用该规则?我可以在弹出功能中没有免费项目从列表中弹出项目吗? 我想要实现的是在程序启动时只分配一次列表,并避免在每次调用pop,push函数时解除分配和分配内存。我想要pop项目,使用项目并再次推送它(在程序的其他部分)列表以供重复使用。 这种方法有问题吗?
感谢我提前征求您的意见和帮助。
答案 0 :(得分:3)
当你不再需要它们时,你必须确保释放分配的内存,这就是重点。
如果您在任何情况下丢失了对动态分配地址的引用而没有释放它,那么您将有内存泄漏,呃:
void pop() {
// get element from stack
// use it
// not call free
}
如果您没有将弹出项目的地址存储在任何地方,这将产生泄漏。
如果您想重复使用已分配的项目,那么您可以自由地执行此操作,在这种情况下,您不应该释放它们,例如:
void push() {
struct Node *ptr = pop_unused_node();
if (!ptr) // if no unused node is found then we need a new one
ptr = malloc(sizeof(struct Node));
*ptr = data;
push(ptr);
}
void pop() {
struct Node *ptr = pop();
// use data
push_unused_node(ptr);
}
void clearup() {
for each node in unused list
free(node);
for each node in stack
free(node);
}
答案 1 :(得分:2)
我希望你所看到的所有实现都在push()中分配节点。
当然,你可以按自己喜欢的方式制作自己的流行音乐;只要你完成它们就不要忽视免费节点。
答案 2 :(得分:1)
答案 3 :(得分:1)
pop()
通常释放内存的原因是因为传统意义上pop()
操作是链接列表最后一次能够“看到”元素。
大多数list
实施都不具有侵入性,因此您将一些您知道的数据类型存储到list
中,但list
本身的内部详细信息尚不清楚。在这种方法中,对于那些实现中的list
来说,该对象的“管家细节”通常会在push()
中分配,使pop()
成为他们被释放的合理位置。
由于用户可能想要检查“next”元素(没有从列表中弹出它),大多数实现都有一个front()
(或类似的)成员函数,允许检查下一个值,pop()
只删除该项(并且没有返回值)。
侵入式数据结构对其中可存储的内容施加了更多限制,但在手动内存管理方面也提供了更大的灵活性(如果这就是您所追求的)。
答案 4 :(得分:0)
你弹出一个值时所见的所有实现的原因是因为它们负责内存中的那个位置。如果你分配任何东西,你的工作就是取消分配。
但这是编程。计算机会做任何你告诉它的事情,所以如果你认为这对你更好,那就去做吧。您可以在没有内存分配或释放的情况下实现自己的链表类。我当然不会推荐它,因为我认为你会遇到更多的问题,如果你只是让列表类分配和解除分配就像你想要的那样,但是,这一切都取决于你。 / p>