在C ++中列出析构函数

时间:2012-05-26 20:32:28

标签: c++ linked-list destructor

我刚刚实施了链接列表。它工作得非常好,但即使很难我也看到了我无法在Node上创建工作析构函数的符号,这就是为什么它在代码中没有实现。

  1. 我需要在节点
  2. 上实现工作析构函数
  3. List的析构函数,但这个很简单我只使用Node类的析构函数(但我需要这个)。
  4. 让List对Node友好,所以我不必使用getNext(),但我想我可以 我自己处理(不确定如何,但我会发现)。
  5. 请查看完全正常的代码,如果你复制它就行了。

    #include <cstdio>
    #include <cmath>
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    using namespace std;
    
    class Node {
    public:
        Node(Node* next, int wrt) {
            this->next = next;
            this->wrt = wrt;
        }
    
        Node(const Node& obiekt) {
            this->wrt = obiekt.wrt;
            this->next = obiekt.next;
        }
        ~Node() {}
    
        void show() {
            cout << this->wrt << endl;
        }
    
        int getWrt(){
            return this->wrt;
        }
    
        Node* getNext(){
            return this->next;
        }
    
        void setNext(Node* node){
            this->next = node;
        }
    
     private:
        Node* next;
        int wrt;
    };
    
    class List{
    public:
        List(int wrt){
            this->root = new Node(NULL, wrt);
        }
    
        List(const List& obiekt){
            memcpy(&this->root,&obiekt.root,sizeof(int));
            Node* el = obiekt.root->getNext();
            Node* curr = this->root;
            Node* next;
            while(el != NULL){
                memcpy(&next,&el,sizeof(int));
                curr->setNext(next);
                curr = next;
                next = curr->getNext();
                el = el->getNext();
        /*      curr->show();
                next->show();
                el->show(); */
            }
        }
    
        void add(int wrt){
            Node* node = new Node(NULL, wrt);
            Node* el = this->root;
            while(el->getNext() != NULL){
                //el->show();
                el = el->getNext();
            }
            el->setNext(node);
        }
    
        void remove(int index){
            Node* el = this->root;
            if(index == 0){
                 //deleting old one
                 this->root = this->root->getNext();
            }
            else{
                int i  = 0;
                while(el != NULL && i < index - 1){
                //  el->show();
                    el = el->getNext();
                    i++;
                }
                if(el!=NULL){
                    Node* toRem = el->getNext();
                    Node* newNext = toRem->getNext();
                    el->setNext(newNext);
                    //deleteing old one
                }
            }
        }
    
        void show(){
            Node* el = this->root;
            while(el != NULL){
                el->show();
                el = el->getNext();
            }
        }
    
        ~List(){}
    
    private:
        Node* root;
    };
    
    int main(){
        List* l = new List(1); //first list
        l->add(2);
        l->add(3);
        l->show();
        cout << endl;
    
        List* lala = new List(*l); //lala is second list created by copy cosntructor
        lala->show();
        cout << endl;
    
        lala->add(4);
        lala->remove(0);
        lala->show();
    
        return 0;
    }
    

3 个答案:

答案 0 :(得分:1)

delete与先前分配的指向链表的指针一起使用时,或者当链表变量超出范围时(例如,从a返回时,本地变量被销毁),将调用链表析构函数。功能)。

链表的析构函数应负责释放先前为节点保留的内存(即使用add操作)。因此,基本上,您需要遍历节点列表并对每个节点应用delete操作。有一个小技巧:当您要删除节点时,必须注意不要丢失指向下一个元素的指针(当删除节点时,您无法确定next成员是否仍然有效)。

答案 1 :(得分:1)

我建议你从实现List的析构函数开始。由于您使用new动态分配了内存,因此应使用delete释放内存。 (如果您使用new[],则为delete[]):

~List()
{
    Node* currentNode = this->root; // initialize current node to root
    while (currentNode)
    {
        Node* nextNode = currentNode->getNext();    // get next node
        delete currentNode;                         // delete current
        currentNode = nextNode;                     // set current to "old" next
    }
}

一旦你有了正确的析构函数,你应该尝试复制构造函数是否正确:

List* lala = new List(*l);
delete l; // delete list that was used to create copy, shouldn't affect copy

您会发现您的复制构造函数错误,并导致您的应用程序崩溃。为什么?因为复制构造函数的目的是创建 new 对象作为现有对象的副本。您的复制构造函数只是复制指针,假设sizeof(Node*)等于sizeof(int)。它应该是这样的:

List(const List& list)
{
    // if empty list is being copied:
    if (!list.root)
    {
        this->root = NULL;
        return;
    }

    // create new root:
    this->root = new Node(NULL, list.root->getWrt());

    Node* list_currentNode = list.root;
    Node* this_currentNode = this->root;
    while (list_currentNode->getNext())
    {
        // create new successor:
        Node* newNode = new Node(NULL, list_currentNode->getNext()->getWrt());
        this_currentNode->setNext(newNode);
        this_currentNode = this_currentNode->getNext();
        list_currentNode = list_currentNode->getNext();
    }
}

此外,您的函数remove是错误的,因为它“删除”对某个节点的引用,但从不释放此节点所在的内存。应该调用delete以释放这段记忆。

“我需要在节点上实现工作析构函数” - 不,你没有。节点本身不分配任何内存,因此它不应释放任何内存。节点不应该负责销毁Node* next,也不应该清理存储它的内存。不要实现析构函数也不要复制Node的构造函数。您还想阅读:What is The Rule of Three?

“让列表对节点友好,所以我不必使用getNext()” - 你想在Node类中说class Listfriend

class Node
{
    friend class List; // <-- that's it

请注意,从您包含代码的这5个标头中只需要一个:<iostream>。 另请注意,在文件开头写using namespace std;被视为不良做法,因为它可能会导致某些类型的名称变得模糊不清。在小范围内明智地使用它或改为使用std::前缀。

答案 2 :(得分:0)

如果你想为你的Node创建一个析构函数,它实际上应该很简单。

这是:

class Node {
    private:
        int wrt;
        Node* next;
    public:
        Node(Node* next, int wrt) {
            this->next = next;
            this->wrt = wrt;
        }

        // Your desired destructor using recursion
        ~Node() {
            if ( next != NULL )
                delete next;
        }
};

这很简单:)

基本上,在删除Node之前,如果next不为空,我们将删除next,这将再次调用next的析构函数,如果next-&gt; next不为空,则再次调用析构函数

然后最后所有节点都被删除。

递归处理整个事情:)