【问题标题】:Why do we use malloc in linkedlist while inserting a node?为什么我们在插入节点时在链表中使用 malloc?
【发布时间】:2021-11-30 20:33:13
【问题描述】:
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;
}

【问题讨论】:

  • DMA 不代表动态内存分配。
  • 如果不使用动态内存分配,每个节点的内存从哪里获取?你不能使用局部变量,因为它会在函数返回时消失。
  • @Amit Kumar 有什么问题?如果您不想使用 malloc,请不要使用它。
  • 你觉得没有malloc应该怎么写?
  • @user253751 例如使用数组。:)

标签: c linked-list malloc dynamic-memory-allocation


【解决方案1】:

这关乎对象的生命周期。

C 标准将此描述为“存储持续时间”。三种最常见的类型是

  1. 自动存储时长

  2. 分配的存储持续时间

  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(或朋友)返回,直到您的代码通过调用free 显式终止该对象。这正是您想要的链表。一个可以控制其生命周期的对象。

注意:当你这样做时

struct Node* new_node = malloc(sizeof(struct Node));

有两个物体在起作用。 new_node 本身仍然是一个具有自动存储持续时间的对象(并且只会存在于函数内部),但它的值(即malloc 返回的值)是一个指向具有分配存储持续时间的节点对象的指针。因此,您可以将new_node 的值保存在链表中,并获得指向函数返回时仍然存在的对象的指针。

静态存储对象的生命周期是从程序开始到程序结束。所以这样的对象可以用于链表。您可以编写一个带有静态节点池的程序,并且当您需要链表中的新节点时,您可以从该池中获取一个节点。这是可行的,但需要额外的代码来维护可用节点池(即实现您自己的 Node-malloc/Node-free 版本)。另一个缺点是它将列表的最大长度限制为固定数字(即启动时池中静态节点对象的数量)。

因此,使用具有分配存储持续时间的对象是迄今为止最简单的方法。当您需要一个新节点时,只需调用malloc。完成一个节点后,只需调用free

在某些特殊情况下,您可能会使用具有静态存储持续时间的对象池。

【讨论】:

    猜你喜欢
    • 2012-01-10
    • 2021-07-05
    • 2018-07-28
    • 2017-02-11
    • 2021-02-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多