【问题标题】:use of new operator while creating linked list创建链表时使用 new 运算符
【发布时间】:2011-08-29 17:18:27
【问题描述】:

在以下程序中:

// illustration of linked list
#include <iostream>

using namespace std;

struct node {
    int data;
    struct node* next;
};

struct node* buildList();

int main() {

struct node* head = buildList();
cout << head->data;
}

struct node* buildList() {
    struct node* head = NULL;
    struct node* second = NULL;
    struct node* third = NULL;

    head = new node;      // builds up a pointer structure on heap
    second = new node;
    third = new node;

    head->data = 1;
    head->next = second;

    head->data = 2;
    second->next = third;

    head->data = 3;
    third->next = NULL;

    return head;
}

我不知道new 操作员在这里的工作。他们执行什么任务? (我读到它在堆上分配空间。但我不知道这是什么意思)如果我删除这些语句,则没有输出并且程序崩溃。这是为什么呢?

【问题讨论】:

  • 1) 这是一个“新的表达式”,而不是一个运算符。 2) 扔掉这本书——new 创建一个具有动态存储和生命周期的新对象,这才是最重要的。

标签: c++ list visual-c++ linked-list new-operator


【解决方案1】:

head、second 和 third 变量是指向内存中节点的指针。但是,在您可以使用它们之前,它们必须指向内存中的有效节点。这就是 new 运算符的用武之地。堆只是分配给程序以动态创建对象的内存区域(与堆栈相反。请参阅here 了解区别)。

【讨论】:

    【解决方案2】:

    * 编辑*

    我只是想在回答之前添加:

    简单来说,堆栈是您的程序当前正在工作的地方,并且在某种程度上是临时的。我的意思是你的 main() 函数可能会调用另一个函数。该函数将有自己的范围({} 之间的区域)、自己的局部变量、空间等。它可能会依次调用另一个函数。这些函数一直被放在“堆栈上”。一旦函数返回,它将从堆栈中取出,您将返回到您开始的下一级函数中的点。就像您将一张纸放在当前笔记本上,记下一些笔记,然后将其删除以返回原始页面。 “堆栈变量”是您在函数中以正常方式创建的变量,它们会在离开作用域时死亡/销毁。

    堆变量是静态/全局变量,或者是使用“new、malloc 等”创建的变量。这些变量是永久的,并且会一直存在/存在,直到您明确调用它们删除。它们将在创建它们的范围之外存活,如果您不跟踪它们,它们的资源将无法释放,并且您将出现内存/资源泄漏。

    普通邮件

    线条:

    struct node* head = NULL;
    struct node* second = NULL;
    struct node* third = NULL;
    

    都在节点声明它是指向节点的指针之后创建指针。这些指针被初始化为 NULL 或 0。指针只是一个内存地址/位置,它还没有节点对象。所以,

    node* ptr = NULL;  //creates pointer to a node object, but no node itself.
    node  obj;         //creates an actual node object on the stack.
    

    指针可用于指向基于堆栈的对象,方法是使用 & 运算符获取其地址,如下所示:

    node obj;  //Real object.
    node* ptr = &obj;  //ptr points to the "address of" obj.
    

    在您的情况下,节点指针不会指向任何东西,直到您使用“new”创建它。之后,指针指向“动态分配”的内存,该内存将永远存在,直到您对其调用“删除”。这样做的好处是内存可以在创建它的函数之外持续存在。所以:

    void myFunction()
    {
        node obj;
    }  //obj dies here.
    
    void myOtherFunction()
    {
        node* ptr = new obj;
    } //the "node" created by new will survive after this.
    

    我可以继续,但您需要阅读 C++ 书籍并理解这一点 - 指针是您需要完全学习的语言的一个关键方面。

    【讨论】:

      【解决方案3】:

      struct node* head = NULL; -> 创建一个指针(因为赋值指向null)

      head = new node; -> 将内存分配给一个节点的大小,并将 head 指向该内存的开头

      所以如果你的指针是 NULL 并且你从不告诉它指向一个节点(或任何东西),那么对该指针或使用该指针的任何操作都会失败

      【讨论】:

        【解决方案4】:

        new 构造一个该类型的新对象。

        在这种情况下,您正在构建一个新节点。但是在某些代码中,您不需要这样做,而是可以简单地使用对象。即节点头;头.数据 = 1; head.next = 废话。

        使用 new 的原因是简单地创建该类型的“新”对象。通常用于动态事物,在这种情况下,它看起来像某种链表,所以是的,你需要新的。但是对于每一个新的,你需要在完成后删除数据 否则你会有内存泄漏,在这种情况下,列表越大,并且你不再解构不再需要的东西,它会浪费更多的内存。

        但是,您根本不需要使用任何此代码。相反,标准库中已经有一个容器可以提供这种类型的支持,另外还有附加功能。

        #include <list> 
        // and use
        std::list<type> data;
        

        您可以轻松地在此列表中插入和删除数据,它会为您处理分配和解除分配;这意味着您永远不需要使用 new 或 delete,您可以放心地假设内存将为您管理并且不会发生内存泄漏。

        【讨论】:

        • 虽然在编写“真实代码”时应该使用标准库的东西,但这看起来像是一本书中的示例代码(即学习指针和数据结构)。
        猜你喜欢
        • 1970-01-01
        • 2023-03-29
        • 1970-01-01
        • 1970-01-01
        • 2021-06-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-09
        相关资源
        最近更新 更多