为什么我们在插入节点时在链表中使用malloc?
Why do we use malloc in linkedlist while inserting a node?
void push(struct Node** head_ref, int new_data)
{
struct Node* new_node = (struct Node*) malloc(sizeof(struct Node)); // WHY this?
new_node->data = new_data;
new_node->next = (*head_ref);
(*head_ref) = new_node;
}
这是关于对象的生命周期。
C 标准将此描述为“存储持续时间”。最常见的 3 种类型是
自动存储时长
分配的存储期限
静态存储时长
具有自动存储持续时间的对象的生命周期仅限于定义对象的块。例如,函数中定义的变量将仅存在于函数内部。所以如果你这样做了
void push(struct Node** head_ref, int new_data)
{
struct Node new_node; // new_node has automatic storage duration
// so it only exist within this function
new_node.data = new_data;
new_node.next = (*head_ref);
(*head_ref) = &new_node; // Very bad... never do this
}
你最终会遇到 *head_ref
指向死对象的情况。
所以对于链表,你就是不能使用局部变量。
具有已分配存储持续时间的对象的生命周期从 malloc
(或朋友)return 开始,直到您的代码通过调用 free
显式终止该对象。这正是您想要的链表。您可以控制其生命周期的对象。
注意:当你这样做时
struct Node* new_node = malloc(sizeof(struct Node));
游戏中有两个对象。 new_node
本身仍然是一个具有自动存储持续时间的对象(并且只会存在于函数内部)但是它的值(即由 malloc
编辑的值 return )是一个指向节点对象的指针具有分配的存储持续时间。因此,您可以将 new_node
的值保存在链表中,并有一个指向在函数 returns.
时仍然存在的对象的指针
静态存储对象的生命周期是从程序开始到程序结束。所以这样的对象可以用于链表。您可以编写一个带有静态节点池的程序,只要您需要链表中的新节点,就可以从该池中获取一个节点。这是可行的,但需要额外的代码来维护可用节点池(即实现您自己的 Node-malloc/Node-free 版本)。另一个缺点是它将列表的最大长度限制为固定数量(即启动时池中静态节点对象的数量)。
因此,使用分配了存储持续时间的对象是迄今为止最简单的方法。当您需要一个新节点时,只需调用 malloc
。完成节点后,只需调用 free
.
在某些特殊情况下,您可能会选择具有静态存储持续时间的对象池。
void push(struct Node** head_ref, int new_data)
{
struct Node* new_node = (struct Node*) malloc(sizeof(struct Node)); // WHY this?
new_node->data = new_data;
new_node->next = (*head_ref);
(*head_ref) = new_node;
}
这是关于对象的生命周期。
C 标准将此描述为“存储持续时间”。最常见的 3 种类型是
自动存储时长
分配的存储期限
静态存储时长
具有自动存储持续时间的对象的生命周期仅限于定义对象的块。例如,函数中定义的变量将仅存在于函数内部。所以如果你这样做了
void push(struct Node** head_ref, int new_data)
{
struct Node new_node; // new_node has automatic storage duration
// so it only exist within this function
new_node.data = new_data;
new_node.next = (*head_ref);
(*head_ref) = &new_node; // Very bad... never do this
}
你最终会遇到 *head_ref
指向死对象的情况。
所以对于链表,你就是不能使用局部变量。
具有已分配存储持续时间的对象的生命周期从 malloc
(或朋友)return 开始,直到您的代码通过调用 free
显式终止该对象。这正是您想要的链表。您可以控制其生命周期的对象。
注意:当你这样做时
struct Node* new_node = malloc(sizeof(struct Node));
游戏中有两个对象。 new_node
本身仍然是一个具有自动存储持续时间的对象(并且只会存在于函数内部)但是它的值(即由 malloc
编辑的值 return )是一个指向节点对象的指针具有分配的存储持续时间。因此,您可以将 new_node
的值保存在链表中,并有一个指向在函数 returns.
静态存储对象的生命周期是从程序开始到程序结束。所以这样的对象可以用于链表。您可以编写一个带有静态节点池的程序,只要您需要链表中的新节点,就可以从该池中获取一个节点。这是可行的,但需要额外的代码来维护可用节点池(即实现您自己的 Node-malloc/Node-free 版本)。另一个缺点是它将列表的最大长度限制为固定数量(即启动时池中静态节点对象的数量)。
因此,使用分配了存储持续时间的对象是迄今为止最简单的方法。当您需要一个新节点时,只需调用 malloc
。完成节点后,只需调用 free
.
在某些特殊情况下,您可能会选择具有静态存储持续时间的对象池。