C++中的列表析构函数 [英] List destructor in C++

查看:48
本文介绍了C++中的列表析构函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've just implemented the Linked List. It works perfectly fine but even tough I've seen notation I am unable to create working destructor on Node, that's why it's unimplemented here in code.

  1. 我需要在节点上实现工作析构函数
  2. List 的析构函数,但这个很简单,我将只使用 Node 类的析构函数(但我需要这个).
  3. 使列表对 Node 友好,这样我就不必使用 getNext(),但我想我可以自己处理(不知道如何处理,但我会找到的).

请看代码,非常好,复制即可.

Please look at the code it is perfectly fine, just will work if you copy it.

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

推荐答案

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

I suggest you to start with implementing destructor of List. Since you dynamically allocated memory by using new, you should free it by using delete. (If you used new[], it would be 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
    }
}

一旦你有了合适的析构函数,你应该试试你的拷贝构造函数是否正确:

Once you have proper destructor, you should try whether your copy constructor is correct:

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

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

you will find out that your copy constructor is wrong and also causes your application to crash. Why? Because purpose of copy constructor is to create a new object as a copy of an existing object. Your copy constructor just copies pointers assuming sizeof(Node*) equal to sizeof(int). It should look like this:

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 以释放此内存.

Also your function remove is wrong since it "removes" reference to some Node but never frees memory where this Node resides. delete should be called in order to free this memory.

我需要在节点上实现工作析构函数" - 不,你不需要.Node 本身不分配任何内存,因此它不应该释放任何内存.Node 不应该负责销毁 Node* next 也不应该负责清理存储它的内存.不要实现 Node.js 的析构函数或复制构造函数.您还想阅读:什么是三法则?

"I need to implement working destructor on node" - No, you don't. Node itself doesn't allocate any memory, thus it shouldn't free any memory. Node shouldn't be responsible for destruction of Node* next nor cleaning memory where it's stored. Don't implement destructor nor copy constructor of Node. You also want to read this: What is The Rule of Three?

使列表对 Node 友好,这样我就不必使用 getNext()" - 您想在 Node 类中说,class List 是它的朋友:

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

请注意,在包含代码的这 5 个标头中,您只需要一个:.另请注意,在文件开头编写 using namespace std; 被认为是不好的做法,因为它可能会导致您的某些类型的名称变得不明确.在小范围内明智地使用它或使用 std:: 前缀代替.

Note that from these 5 headers that you include your code requires only one: <iostream>. Also note that writing using namespace std; at the beginning of the file is considered bad practice since it may cause names of some of your types become ambiguous. Use it wisely within small scopes or use std:: prefix instead.

这篇关于C++中的列表析构函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆