簡體   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