2017-04-19 62 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; 
} 
相关问题