链表头指针在传递给函数c++时发生变化

linked list head pointer changing when passed to function c++

本文关键字:c++ 变化 函数 指针 表头 链表      更新时间:2023-10-16

我在第二年的编程课上遇到了一个问题,这个问题涉及创建一组双链表来表示医院以及医院中的医生和患者。一家医院有一份医生名单,每个医生都有一份病人名单。我的问题是,当我调用"hireDoctor"函数将医生添加到医院的列表中时,不知何故,头指针发生了变化。这是我的代码:

/* adds a Doctor to the Hospital's list of Doctors */
void Hospital::hireDoctor(Doctor *doc)
{
DoctorNode node;
node.value = *doc;
DoctorNode* curr;
if (drListHead == NULL) {    //if doctor list is empty,
drListHead = &node;    //insert the node at the beginning
node.next = NULL;
node.prev = NULL;
} else {
curr = drListHead;
//traverse list until equal or greater (alphabetical) value is found:
while (curr->value.getLast().compare(node.value.getLast()) < 0 &&
curr->value.getFirst().compare(node.value.getFirst()) < 0) {
curr = curr->next;
}
if (curr->prev == NULL) {     //if inserting at the beginning of the list
drListHead = &node;
node.prev = NULL;
node.next = curr;
} else if (curr->next == NULL) { //if the end of the list has been reached
curr->next = &node;
node.prev = curr;
node.next = NULL;
} else {              //insert the new DoctorNode in the middle:
curr->next->prev = &node;
node.next = curr->next;
curr->next = &node;
node.prev = curr;
}
}

列表中的每个节点都定义为一个结构:

struct DoctorNode {
Doctor value;
DoctorNode *next;
DoctorNode *prev;
}

因此,在完成了一次"雇佣医生"功能后,如果我"雇佣"了一位名叫约翰·史密斯的医生,我希望ListHead医生能指向约翰·史密斯,这似乎就是发生的事情。然而,在第二次通过该功能雇佣Jane Doe时,drListHead似乎已经在进入该功能时指向Jane Doe。我不知道它在哪里变了。任何想法都将不胜感激!

问题就在这里:

if (drListHead == NULL) {    //if doctor list is empty,
drListHead = &node;    //insert the node at the beginning  <------
node.next = NULL;
node.prev = NULL;
} 

您的节点在堆栈上初始化,退出hireDoctor后,它将指向堆栈的地址。下次调用hireDoctor时,节点再次指向相同的地址,即Jane Doe(这只是巧合)。你需要这个:

if (drListHead == NULL) {    //if doctor list is empty,
drListHead = new DoctorNode();    //heap allocation 
drListHead->next = NULL;
drListHead->prev = NULL;
}

但请记住,您必须实现释放未使用的内存。

问题就在这里:DoctorNode node;这样,您的节点在函数中具有可见性;当函数结束时,该变量将被销毁。因为销毁的变量是可重复使用的ram,但在这个ram不被其他东西使用之前不会更改,所以您认为它仍然具有正确的值。下一个医生创造要求一些公羊,和"随意"相同的公羊之前的医生是免费的,并用于新的医生。这意味着你已经重写了头所指向的ram,也丢失了旧医生的所有数据(好吧,数据仍然在这里,只是你没有更多的指针指向它,所以它丢失了ram中的某个地方;从技术上讲,这被称为"垃圾")。

寻找"可变可见性"以更好地解释

解决方案是改为指针

DoctorNode node*;

使用"new"来保留ram,直到通过调用"delete"明确释放该ram。如果您销毁doctor而不释放使用"delete"分配的所有指针,那么您也在创建垃圾。看见http://www.codeproject.com/Articles/6555/To-new-is-C-To-malloc-is-C-To-mix-them-is-sin

一个常见的问题是用垃圾填充RAM,这会导致程序甚至操作系统崩溃。