在C++中删除对象

35

这是我的一个示例代码:

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

我在Visual Studio中运行它,在带有“delete 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
你下面提到的 loadLeaves 函数是否在堆上分配对象?还是返回本地地址之类的东西?记住,你只能删除你 new 的东西... - Evan Teran
请确保析构函数不是私有的! - Vaibhav
6个回答

41
这是管理动态分配内存的一种常见方式,但并不是一个好的方式。这种代码很脆弱,因为它不是异常安全的:如果在创建对象和删除对象之间抛出异常,那么会导致该对象泄漏。更好的方法是使用智能指针容器,可以获得范围绑定的资源管理(通常称为资源获取即初始化或RAII)。以下是自动资源管理的示例:
void test()
{
    std::auto_ptr<Object1> obj1(new Object1);

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

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

4
这个回答仍然正确吗?显然,auto_ptr现在已经被弃用了。 https://dev59.com/hXE95IYBdhLWcg3wOLQ1 管理员能编辑一下这个答案吗? - kutuzof
这是相对正常的谷歌搜索中出现的第一个答案。 - kutuzof

6
您的代码确实使用了创建和删除动态对象的常规方式。是的,删除操作(delete)会调用对象的析构函数,这在语言标准中也有明确规定!如果您不是直接实例化Object1而是其某个子类,我要提醒您,任何希望被继承的类都必须有一个虚析构函数(这样可以在类似于这种情况下调用正确的子类析构函数),但如果您的示例代码确实代表了您的实际代码,那么这不可能是您当前的问题——可能存在于您没有展示给我们的析构函数代码中,或者是在该函数内部或其调用的函数中存在堆破坏的问题……另外,顺便说一下,如果您总是在退出实例化它的函数之前删除该对象,那么将其声明为动态对象就没有意义了——只需将其声明为该函数的本地变量(存储类auto,这是默认值)即可!

4

这不是释放与对象相关的内存的常规方式吗?

是的,没错。

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

是的

请确保您没有重复删除您的对象。


1
那么,为什么这是正常的呢? 由于它是一个指针变量,如何才能自动删除它呢? 发生的情况是首先我删除了对象,然后到达 '}' 行时再次调用析构函数,这就导致了问题。 我的问题是为什么它会自动调用析构函数? 如果这是正常的,那么为什么人们在这种情况下要删除对象? - Nima
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()将自动调用。请展示完整的代码。 - Prasoon Saurav

2
如果在delete行崩溃,则几乎可以确定您某种方式破坏了堆。要诊断问题,我们需要查看更多代码,因为您提供的示例没有错误。
也许您在堆上有一个缓冲区溢出,这导致堆结构损坏,甚至可能是像“double free”(或在c++中是“double delete”)这样简单的问题。
还有,正如The Fuzz所指出的那样,您的析构函数可能存在错误。
是的,调用析构函数然后释放内存是delete的两个目的之一,这是完全正常和预期的。

2

saveLeaves(vec,msh);
我假设这个函数将指针msh放入vec中。由于msh只是指向内存的指针,如果你删除它,它也会在向量中被删除。


2

这是对James答案的更新。

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

是的。这是释放内存的常规方式。但是new/delete操作符会导致内存泄漏问题。

自从c++17已经删除了auto_ptr auto_ptr。我建议使用shared_ptr或unique_ptr来处理内存问题。

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

} // The object is automatically deleted when the scope ends or reference counting reduces to 0.
  • 移除auto_ptr的原因是在复制语义方面不稳定。
  • 如果您确定在作用域内没有发生复制,则建议使用unique_ptr。
  • 如果指针之间存在循环引用,请考虑使用weak_ptr。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接