C ++非预期的析构函数调用

时间:2015-05-26 13:41:53

标签: c++ explicit-destructor-call

我在C ++中有关于数据结构的功课,但我遇到了一个奇怪的问题。对不起,如果标题有点不明显。首先,对于家庭作业,我们已经给出了PaperRepository类的头文件来实现。本课程通过循环双向链表保存论文信息。每篇论文都有标题,发表论文的期刊,出版年份和由另一个链表类别(排序链表)保存的共同作者列表,这是PaperRepository.h文件

// PaperRepository.h

#include <string>

#include "CDoublyLinkedList.cpp"
#include "Paper.cpp"

using std::string;

class PaperRepository
{
public:
    PaperRepository();
    ~PaperRepository();

    void addPaper( string paperTitle, string journalTitle,int publicationYear );
    void removePaper( string paperTitle );
    void addCoauthor( string paperTitle, string coauthorFirstName,string coauthorLastName, string coauthorInstitution);
    void removeCoauthor ( string coauthorFirstName, string coauthorLastName);
    void showAllPapers();
    void showCoauthor( string coauthorFirstName, string coauthorLastName );
    void showJournal( string journalTitle );

private:
    CDoublyLinkedList<Paper> papers;
};

为了保存论文,我实施了一个循环的双向链表类(正如我的导师所说)。这是CDoublyLinkedList.cpp

// CDoublyLinkedList.cpp

#include <cstdlib>
#include <iostream>

template <class T> class CDoublyLinkedList
{
private:
    struct Node
    {
        T data;
        Node* prev,*next;
        Node(const Node& other)
        {
            other.data = data;
            other.prev = prev;
            other.next = next;
        }

        Node(T data)
        {
            this->data = data;
            prev = NULL;
            next = NULL;
        }
    };

    Node* head;
    int listSize;

public:
    CDoublyLinkedList()
    {
        head = NULL;
        listSize = 0;
    }

    ~CDoublyLinkedList()
    {
        std::cout<<"CDoublyLinked List's destructor is called."<<std::endl;
        Node* cur = head;

        for(int ctr = 0;ctr < listSize ; ctr++)
        {
            head = cur->next;
            delete cur;
            cur = head;
        }
    }

    void addToBeginning(T data)
    {
        Node* newNode = new Node(data);
        std::cout<<"inside add to beginning"<<std::endl;

        if(listSize == 0)
        {
            newNode->next = NULL;
            newNode->prev = NULL;
            head = newNode;
            listSize++;
            return;
        }
        if(listSize == 1)
        {
            newNode->prev = head;
            newNode->next = head;
            head->prev = newNode;
            head->next = newNode;
            head = newNode;
            listSize++;
            return;
        }

        newNode->next = head;
        newNode->prev = head->prev;
        head->prev->next = newNode;
        head->prev = newNode;
        head = newNode;
        listSize++;
    }

    void addToEnd(T data)
    {
        Node* newNode = new Node(data);

        //newNode->data = data;
        if(listSize == 0)
        {
            newNode->next = NULL;
            newNode->prev = NULL;
            head = newNode;
            listSize++;
            return;
        }
        if(listSize == 1)
        {
            newNode->next = head;
            newNode->prev = head;
            head->next = newNode;
            head->prev = newNode;
            listSize++;
            return;
        }

        newNode->next = head;
        newNode->prev = head->prev;
        head->prev->next = newNode;
        head->prev = newNode;
        listSize++;
    }

    void add(T data)
    {
        std::cout<<"Inside CDoublyLinkedList add."<<std::endl;
        if(listSize == 0)
        {
            addToBeginning(data);
            std::cout<<"After adding to the beginning"<<std::endl;
        }
    else
        addToEnd(data);
    }

    void clearList()
    {
        Node* cur = head;
        for(int ctr = 0;ctr < listSize ; ctr++)
        {
            head = cur->next;
            delete cur;
            cur = head;
        }

        listSize = 0;
        head = NULL;
    }
};

这是LinkedList.cpp。由于我没有在列表中添加或删除任何共同作者,因此我不在此处编写添加和删除方法。 LinkedList.cpp

// LinkedList.cpp

#include <iostream>
#include <cstdlib>

template <class T> class LinkedList
{
private:
    struct Node
    {
        T data;
        Node *next;
        Node(const Node& other)
        {
            other.data = data;
            other.next = next;
        }
        Node(T data)
        {
            this->data = data;
            next = NULL;
        }
    };

    Node *header;
    int listSize;

public:
    LinkedList()
    {
        std::cout<<"LinkedList's constructor is called."<<std::endl;
        header = NULL;
        listSize = 0;
    }
    ~LinkedList()
    {
        std::cout<<"Linked List destructor is called"<<std::endl;
        Node* temp;
        while(header)
        {
            temp = header;
            header = header -> next;
            delete temp;
        }
    }

我在PaperRepository类的add方法的实现在这里: PaperRepository.cpp

// PaperRepository.cpp

#include <cstdlib>
#include "PaperRepository.h"
#include <iostream>

PaperRepository::PaperRepository()
{
}

PaperRepository::~PaperRepository()
{
    papers.clearList();
}

void PaperRepository::addPaper( string paperTitle, string journalTitle,int
publicationYear )
{
    std::cout<<"add paper is called."<<std::endl;
    Paper newPaper(paperTitle,journalTitle,publicationYear);
    std::cout<<"new paper is created."<<std::endl;
    std::cout<<"before adding paper."<<std::endl;
    papers.add(newPaper);
    std::cout<<"after adding paper."<<std::endl;
}

我没有添加其他方法,因为我的问题始于add方法。最后,我的Paper和CoAuthor类的重要部分。 Paper.cpp

// Paper.cpp

#include <string>
#include <iostream>
#include "LinkedList.cpp"
#include "CoAuthor.cpp"

using std::string;

class Paper
{
private:
    string title;
    string journal;
    int year;
    LinkedList<CoAuthor> coAuthors;

public:
    Paper()
    {
        title = "";
        journal = "";
        year = 0;
    }

    Paper(string title, string journal, int year)
    {
        this->title = title;
        this->journal = journal;
        this->year = year;
    }

    ~Paper()
    {
        coAuthors.clearList();
    }
};

和CoAuthor.cpp

// CoAuthor.cpp

#include <iostream>
#include <string>

using std::string;

class CoAuthor
{
private:
    string name,lastName,institution;

public:
    CoAuthor(string name,string lastName, string institution)
    {
        this->name = name;
        this->lastName = lastName;
        this->institution = institution;
    }

    CoAuthor()
    {
        name = "";
        lastName = "";
        institution = "";
    }
};

这是我正在测试的文件。 main.cpp中

// main.cpp

#include "PaperRepository.h"
#include <iostream>
#include <string>

int main()
{
    PaperRepository myRep;
    myRep.addPaper("MyTitle","Journal",1950);
    std::cout<<"End of main..."<<std::endl;

    return 0;
}

当我运行程序时,我看到在调用CDoublyLinkedList.cpp文件的add方法中的命令并执行“Node newNode = new Node(data)”时,将调用LinkedList类的析构函数。这对我来说很奇怪。另外,LinkedList类的析构函数总共被调用了5次。我将数据添加到循环双向链表类,并调用其他链表类的析构函数。对不起,这有点长,但我不能解释自己。这是main.cpp文件的输出:

>add paper is called.
> *LinkedList's constrctor is called.
> *new paper is created.
> before adding paper
> Inside Doubly Linked List's add
> LinkedList's constructor is called.
> LinkedList's destructor is called.
> inside addToBeginning.
> LinkedList's destructor is called.
> After addToBeginning method
> LinkedList's destructor is called.
> after adding paper
> LinkedList's destructor is called.
> End of main...
> Linked List's destrutor is called.
> CDoublyLinkedList's destructor is called.

1 个答案:

答案 0 :(得分:2)

您正在为链接列表添加值,而不是指针。首先,您在堆栈上实例化(例如)一个新的Paper对象。然后,您add()到链接列表,按值传递对象,复制对象。然后函数范围结束,并且本地Paper对象被销毁。

您还有其他各种错别字和类的基本问题。例如:

struct Node{
    T data;
    Node *next;
    Node(const Node& other){
        other.data = data;
        other.next = next;
    }
...
}

那不应该编译。它应该是一个复制构造函数,它将成员设置为other输入参数提供的值,而不是相反。该参数为const,因此您无法对其进行修改,这就是它不应该编译的原因。

一般情况下,我建议您与教师进行简短的会谈,讨论您的代码。