传递给函数c ++时链表头指针的变化

时间:2012-10-10 13:06:29

标签: c++ pointers linked-list

我的第二年编程课程存在问题,涉及创建一组代表医院的双重链表,以及医院的医生和患者。医院有一份医生名单,每位医生都有一份患者名单。我的问题是,当我调用“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;
    }

所以经过一次雇佣医生的功能,如果我“聘请”一位名叫约翰史密斯的医生,我希望drListHead指向John Smith,这似乎就是这样。然而,在第二次通过该功能,雇用Jane Doe时,似乎drListHead在进入该功能时已经已经指向Jane Doe。我无法弄清楚它在哪里被改变了。任何想法都将不胜感激!

2 个答案:

答案 0 :(得分:1)

问题出在这里:

        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;
            }

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

答案 1 :(得分:0)

问题在于: DoctorNode node; 这样你的节点就可以在函数中看到它;当函数结束时,该变量被销毁。 因为被破坏的变量是可重复使用的ram,但是在这个ram没被其他东西使用之前不会改变,你认为仍然有正确的值。 下一个医生创建要求一些公羊,并且“随便”与之前医生相同的公羊免费并用于新医生。这意味着你已经把头部指向的ram重新编号,也丢失了老医生的所有数据(好吧,数据仍在这里,只是你没有更多的指针,所以它在某处丢失了RAM;这在技术上称为“垃圾”)。

寻找“变量可见性”以获得更好的解释

解决方案是改为指针

DoctorNode node*;

使用“new”来保留ram,直到你通过调用“delete”显式释放该ram。如果你在没有释放使用“删除”分配的所有指针的情况下销毁医生,那么你也在制造垃圾。 见http://www.codeproject.com/Articles/6555/To-new-is-C-To-malloc-is-C-To-mix-them-is-sin

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