【问题标题】:Deleting an object in C++在 C++ 中删除对象
【发布时间】:2011-03-26 15:08:03
【问题描述】:

这是我的示例代码:

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

我在 Visual Studio 中运行它,它在“delete obj;”行崩溃。 这不是释放与对象关联的内存的正常方法吗? 我意识到它会自动调用析构函数……这正常吗?


这是一个代码sn-p:

    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-&gt;code 只是有关要打开的文件的信息)

我应该删除delete msh; 行吗?

【问题讨论】:

  • 让我们看看你的班级是什么样子的。你的析构函数可能有问题。
  • 下面提到的loadLeaves函数是否在堆上分配对象?还是返回本地地址或类似地址?记住,你只能deletenew...
  • 确保析构函数不是私有的!

标签: c++ object memory-management new-operator


【解决方案1】:

只是詹姆斯回答的更新。

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

是的。这是释放内存的正常方式。但是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的原因是auto_ptr在应对语义的情况下不稳定
  • 如果您确定在作用域期间没有发生任何应对,建议使用 unique_ptr。
  • 如果指针之间存在循环引用,我建议看一下weak_ptr。

【讨论】:

    【解决方案2】:

    saveLeaves(vec,msh);
    我假设将msh 指针放在vec 内。由于msh只是一个指向内存的指针,如果你删除它,它也会在vector内部被删除。

    【讨论】:

      【解决方案3】:

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

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

      使用智能指针容器要好得多,您可以使用它来进行范围绑定的资源管理(通常称为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

      至于为什么你的程序在你删除对象时崩溃,你没有给出足够的代码让任何人都能够确定地回答这个问题。

      【讨论】:

      【解决方案4】:

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

      如果您不是直接实例化 Object1 而是它的某个子类,我会提醒您,任何打算从中继承的类都必须有一个 virtual 析构函数(以便正确的子类的析构函数可以在与此类似的情况下调用)——但如果你的示例代码确实代表了你的实际代码,这不可能是你当前的问题——必须是别的东西,也许在你没有向我们展示的析构函数代码中,或者您未在该函数或它调用的代码中显示的代码中的一些堆损坏......?

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

      【讨论】:

        【解决方案5】:

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

        是的。

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

        Yes

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

        【讨论】:

        • 那么,为什么这是正常的?既然是指针变量,自动删除这怎么正常呢?发生的事情是首先我删除对象,然后到达'}'行,它再次调用析构函数,这会导致问题。我的问题是为什么它会自动调用析构函数?如果是正常的,那么为什么人们在这种情况下删除一个对象?
        • 阅读这些:parashift.com/c++-faq-lite/dtors.html#faq-11.9parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.9 Then the destructor Fred::~Fred() will *automagically* get called when you delete ...... 向我们展示完整的代码。
        【解决方案6】:

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

        也许您在堆上发生了缓冲区溢出,从而破坏了堆结构,或者甚至像“双重释放”(或在 c++ 情况下为“双重删除”)这样简单的东西。

        此外,正如 The Fuzz 所指出的,您的析构函数中也可能有错误。

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-04-27
          • 1970-01-01
          • 2016-12-04
          • 2011-03-09
          • 1970-01-01
          • 2013-02-26
          相关资源
          最近更新 更多