在第三次调用中,当地址因本地作用域而被销毁时,temp2->next 如何能够访问第二个节点的地址?


struct node {
    char name[20];
    int age;
    int height;
    node* next; // Pointer to the next node
};
node* startPTR = NULL; // global
void addNode_AT_END() {
    node *temp1;
    node *temp2;
    temp1 = new node;  
    cout << "Enter the name : ";
    cin  >> temp1->name;
    cout << endl << "Enter the age : ";
    cin  >> temp1->age;
    cout << endl << "Enter height : ";
    cin  >> temp1->height;
    temp1->next = NULL;
    if( startPTR == NULL) {
       startPTR = temp1; 
    }  else {
       temp2 = startPTR;
       while( temp2->next != NULL )
           temp2 = temp2->next;
       temp2->next = temp1;
    }
 }

在这个代码片段中,当第三次调用函数时,else部分起作用。将startPTR的地址分配给temp2。在while循环中检查条件时,temp2->next包含什么?(在第三次调用期间)如果你说它包含第二个节点的地址,请告诉它是如何知道第二个节点的地址的,因为我们在使用temp2->next = temp1语句第二次调用函数期间将第二个节点的地址分配给了第一个节点,但由于它的局部作用域,我们丢失了地址。

这是我目前思考的方式。请解释在第三次调用函数时如何检查条件,以及链表是如何形成的?

只有指针变量temp1temp2是局部作用域。实际的链表节点(类型为struct node)是通过调用new在堆上分配的。堆分配的数据一直存在,直到通过调用delete释放。

这意味着temp2->next = temp1行存储了附加到列表尾部的新节点的地址,并且该信息将在后续调用addNode_AT_END函数时可用。

代码似乎有各种各样的问题-你使用全局变量,除非有后续调用delete某处你有内存泄漏,已经有std容器类std::list是可用的…

希望对你有帮助。

编辑:关于你的评论-当你调用new node时,你正在堆上构造一个node对象。该对象在后续调用delete之前可以使用。

当您调用temp2->next = temp1时,以下内容为真:

  1. temp2指向存储列表中最后一个节点的内存地址(该节点将在上次迭代中通过调用new创建)。
  2. 指针变量temp1的值被赋值为列表中最后一个节点(temp2"指向"的数据)的next指针。这意味着该地址存储在中,而不是存储在本地temp2指针变量中。

当你的函数退出时,是的,局部指针变量temp1temp2超出了作用域,但是分配的链表节点不会被销毁-这就是地址存储的地方。

编辑:第二个注释-在函数的else分支中,指针temp2被初始化为指向列表的头行temp2 = startPTR;

下一行(while循环)从头节点遍历链表,直到指针temp2指向列表中的最后一个节点(直到temp2->next = NULL)

在这个阶段,新节点被追加到列表中,如上所述。

在第三次调用期间,while循环的第一次迭代中的temp2->next确实指向第二个节点。这里的关键是

这行

temp1 = new node;

当您使用new操作符时,这将在堆上分配一个对象(动态分配)并返回指向该对象的指针。使用new在堆上分配的任何东西都会一直存在,直到您在指向该内存的指针上使用delete。现在变量temp1本身实际上只是堆栈上的一个指针,它是一个局部变量。这只意味着指针temp1将超出作用域,但是您已经将第一个节点的next指针指向堆上的第二个节点对象,因此它仍然在那里。

相关内容

  • 没有找到相关文章