2017-04-19 65 views
0

我有一個類型,作爲成員指向另一個對象的指針。當創建對象(Demo)時,它將在構造函數中初始化另一個對象(Property)。我認爲如果我有很多這些對象,當我將屬性更改爲不同的東西時,我不想浪費堆空間,因此我將初始化的內存釋放到setProperty中,然後在Demo的解構中再次刪除它,因爲它會已經被設定爲與此不同的東西。但是,這會導致代碼崩潰。爲什麼它在重置時重新分配property會崩潰?C++如何刪除一個默認的對象成員,這是一個指針

class Property{ }; 


class Demo{ 
    protected: 
      Property *property; 
    public: 
      Demo(){ property = new Property();}; 

      void setProperty(Property *p){ 
        delete property; 
        property = p; 
      }; 

      ~Demo(){ 
        delete property; 
      }; 
}; 

int main(){ 
    Property p = Property(); 
    Demo * d = new Demo(); 

    d->setProperty(&p); 

    delete d; 
} 
+1

甚至聲明'財產'在哪裏?此外,您只能使用'delete'來釋放使用'new'創建的東西。 'main()'中的'p'是堆棧分配的,所以'Demo ::〜Demo()'有效地刪除了一個堆棧分配的對象,這是一個未定義的行爲。 – cdhowie

+0

除了這個甚至沒有編譯的事實(「屬性」不存在)之外,這裏有太多的誤解,我甚至不知道從哪裏開始。爲什麼你首先使用動態分配,祈禱告訴? –

+0

您違反了[3條規則](https://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming)),並且您試圖刪除未用' new'。 –

回答

5

您傳遞的對象地址不是由new創建的,然後嘗試delete它。這是未定義的行爲。

最有可能的速成課程解釋是,標準庫也釋放了Property p。您先釋放它,然後在程序結束時再次釋放p

可能的「修復」是傳遞允許刪除的對象,即由new創建。

int main(){ 
    Property *p = new Property(); 
    Demo * d = new Demo(); 

    d->setProperty(p); // Demo is responsible for freeing `p`. 

    delete d; 
} // standard libraries do clean up objects from `main` here 

請注意,有更好和更乾淨的方式來實現你正在嘗試做的事情。這個答案只是解釋了崩潰。

你應該看到這一點,這是很難與這個desing選擇是否應該釋放或不。所以你的代碼依賴於參數的來源。這應該是設計的一面紅旗。

3

通過使用標準庫提供的相應工具消除所有內存管理問題。

#include <memory> 

class Property{ }; 


class Demo{ 
    protected: 
      std::unique_ptr<Property> property; 
    public: 
      Demo() 
      : property { new Property() } 
      { } 

      void setProperty(std::unique_ptr<Property> p){ 
       property = std::move(p); 
      }; 

    // un-necessary 
    //  ~Demo(){ 
    //    delete property; 
    //  }; 
}; 

int main(){ 
    auto p = std::unique_ptr<Property>(new Property); // or in c++14: = std::make_unique<Property>(); 
    auto d = std::unique_ptr<Demo>(new Demo); // or in c++14: = std::make_unique<Demo>(); 

    d->setProperty(std::move(p)); 

    // no longer necessary 
    // delete d; 
} 
相關問題