繁体   English   中英

[c ++]为什么我的类析构函数被调用两次?

[英][c++]Why is my class destructor called twice?

我有这样的代码,

#include <iostream>
#include <string>

using namespace std;

class Heart {
private:
    int bpm;
public:
    Heart(int bpm) : bpm(bpm) {}
    int getBPM() {
        return bpm;
    }
};

class Kidney {
private:
    double PercentFunction;
public:
    Kidney() : PercentFunction(0) {}
    Kidney(double pf) : PercentFunction(pf) {}
    double getPF() {
        return PercentFunction;
    }
};

class Person {
private:
    string fname, lname;
    int age;
    Heart h;
    Kidney* k; 

public:
    Person(string fn, string ln, int age, int bpm, double kpf1, double kpf2) : fname(fn), lname(ln), age(age), h(bpm) {
        k = new Kidney[2];
        k[0] = Kidney(kpf1);
        k[1] = Kidney(kpf2);
        cout << fname << " " << lname << ", aged " << age << ". Heart BPM : " << bpm <<
            ". Kidneys' percent function indices: " << k[0].getPF() << " and " << k[1].getPF() << '.' << endl;
    }
    ~Person() {
        cout << "A person is dying!" << endl;
        delete[] k;
    }


};


int main() {
    Person p = Person("Jack", "Bowen", 24, 60, 0.99, 0.98);
}

然后我运行我的代码,弹出错误(调试断言失败!)。 您还可以看到析构函数被调用两次。 但是如果我删除delete [] k; 在〜Person中,不会出现此类弹出错误。

在Person构造函数中有动态分配:

k = new Kidney[2];
k[0] = Kidney(kpf1);
k[1] = Kidney(kpf2);

所以我认为我应该删除析构函数中的k。 我的问题是为什么析构函数被调用两次,以及如何解决该错误?

我正在使用VS 2013。

谢谢!

问题如下。 在行中

Person p = Person("Jack", "Bowen", 24, 60, 0.99, 0.98);

您正在复制初始化p ,即您正在创建一个临时文件,然后将其复制到Person p; 最后,临时Person("Jack", "Bowen", 24, 60, 0.99, 0.98); 已被破坏,因此Kidney*指针悬空了,因为您未实现复制构造函数且复制内容较浅(即,指针本身正在复制,而不是其指向的对象)。 并且您的析构函数被调用两次,因为它在临时变量的生命期结束时(在语句的末尾)首先被调用,然后在Person pmain()的末尾超出范围时再次被调用。

只要您的类有指针,就实现其复制构造函数和赋值运算符 或者更好的方法是使用智能指针,例如std::shared_ptr ,或者更好的标准容器来跟踪其动态内存,例如std::vector/std::list等。

快速而又肮脏的代码修复程序(但实际上,您将必须实现copy构造函数,因为您将遇到其他所有类型的问题,例如,从函数返回Person或按值传递Person时):

Person p("Jack", "Bowen", 24, 60, 0.99, 0.98);

这样可以避免任何临时情况,并使用直接初始化。

PS:在g++ ,使用-Weffc++编译会警告您这些问题,

警告:“类Person”具有指针数据成员[-Weffc ++],但不会覆盖“ Person(const Person&)” [-Weffc ++]或“ operator =(const Person&)” [-Weffc ++]

我不确定VS是否存在这样的编译器标志。

问题是你的线

Person p = Person("Jack", "Bowen", 24, 60, 0.99, 0.98);

这构造了两个对象:一个在=的右侧,一个在左侧。 由于您没有定义复制构造函数,因此左侧的复制构造函数将简单地将一个相同的指针复制到右侧。 您提到的两个析构函数都是这两个对象, =左边的一个是导致问题显现的一个。

为了解决这个问题,您可以执行以下操作之一:

  1. 正确定义一个复制构造函数,该构造函数将不复制指针,而是分配一个新的指针,复制内部对象,等等。

  2. 更好的方法是用现成的类代替指针,该类为您完成这些事情,例如vector

如前所述,添加复制构造函数/赋值操作应该可以。 但是,如果您只是想解决此问题,使用指针将很容易。

int main() {
    Person *p = new Person("Jack", "Bowen", 24, 60, 0.99, 0.98);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM