2010-08-07 85 views
24

这里是我有一个示例代码:删除在C++的对象

void test() 
{ 
    Object1 *obj = new Object1(); 
    . 
    . 
    . 
    delete obj; 
} 

我在Visual Studio中运行它,并且它崩溃在与线“删除OBJ;”。 这不是通常的方式来释放与对象关联的内存吗? 我意识到它会自动调用析构函数......这是正常的吗?


下面的代码片段:

if(node->isleaf()) 
    { 
     vector<string> vec = node->L; 
     vec.push_back(node->code); 
     sort(vec.begin(), vec.end()); 

     Mesh* msh = loadLeaves(vec, node->code); 

     Simplification smp(msh); 

     smp.simplifyErrorBased(errorThreshold); 

     int meshFaceCount = msh->faces.size(); 

     saveLeaves(vec, msh); 

     delete msh; 
    } 

loadleaves()是从磁盘中读取一个网格,创建一个Mesh对象,并返回它的功能(想vecnode->code是关于刚刚信息文件被打开)

我应该删除delete msh;行吗?

+3

让我们看看你的课堂是什么样子。你的析构函数可能有问题。 – TheFuzz 2010-08-07 02:56:00

+0

下面提到的'loadLeaves'函数是否在堆上分配对象?或者它是否返回本地地址或类似的地址?记住,你只能'删除'你'新'...​​ – 2010-08-07 05:44:29

+0

确保析构函数不是私有的! – Vaibhav 2013-08-08 08:29:56

回答

32

这是不是正常的方式来释放与对象关联的内存吗?

这是管理动态分配内存的常用方法,但这不是一个好方法。这种代码很脆弱,因为它不是异常安全的:如果在创建对象和删除对象之间引发异常,则会泄漏该对象。

使用智能指针容器,您可以使用它来获取作用域绑定资源管理(通常称为resource acquisition is initialization或RAII),这会更好。

自动资源管理的一个例子:

void test() 
{ 
    std::auto_ptr<Object1> obj1(new Object1); 

} // The object is automatically deleted when the scope ends. 

根据你的使用情况,auto_ptr可能无法提供你所需要的语义。在这种情况下,您可以考虑使用shared_ptr。至于为什么当你删除对象时你的程序崩溃了,你没有给出足够的代码给任何人以确定的方式回答这个问题。

2

如果它在delete行崩溃,那么你几乎肯定会以某种方式损坏堆。由于您提供的示例没有错误,因此我们需要查看更多代码来诊断问题。

也许你在堆上有一个缓冲区溢出,这会破坏堆结构,甚至像“双免费”(或在C++的情况下“双删除”)那样简单。另外,正如The Fuzz指出的那样,你的析构函数也可能有错误。

是的,这是完全正常的,并且期望delete调用析构函数,这实际上是它的两个目的之一(调用析构函数然后释放内存)。

3

这不是通常的方式来释放与对象关联的内存吗?

是的。

我意识到它会自动调用析构函数......这是正常的吗?

Yes

确保你没有double delete你的对象。

+1

那么,为什么这是正常的? 由于它是一个指针变量,这是如何正常自动删除? 发生了什么是首先我删除对象,然后到达行'}'它再次调用析构函数,这会导致问题。 我的问题是为什么它会自动调用析构函数? 如果这是正常的,那么为什么人们在这种情况下删除一个对象? – Nima 2010-08-07 02:58:46

+1

阅读这些:http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.9和http://www.parashift.com/c++-faq-lite/freestore-mgmt.html# faq-16.9 '然后析构函数Fred ::〜Fred()将自动*在你删除时被调用......' 向我们展示完整的代码。 – 2010-08-07 03:06:35

6

你的代码的确使用正常的方式来创建和删除一个动态对象。是的,这完全正常(并且确实由语言标准保证!)delete将调用对象的析构函数,就像new必须调用构造函数一样。

如果没有实例Object1直接,但一些子类上,我想提醒大家,任何类打算从继承必须有一个虚拟析构函数(以便正确的子类的析构函数可以在类似的情况下被调用到这个) - 但是如果你的示例代码确实代表了你的实际代码,这不可能是你目前的问题 - 必须是别的东西,也许在你没有展示给我们的析构函数代码中,或者是一些堆 - 你没有在该功能中显示的代码或它所调用的代码...?

顺便说一句,如果你总是要在退出实例化它的函数之前删除该对象,那么使该对象变为动态没有意义 - 只需将它声明为本地(存储类auto,就像默认)所说功能的变量!

1

saveLeaves(vec,msh);
我假设需要msh指针,并把它放在vec里面。由于msh只是一个指向内存的指针,如果你删除它,它也会被删除。