如果我在c ++中调用delete或析构函数就足够了

时间:2013-06-20 13:48:02

标签: c++

如果在一个函数中,我新建一个对象,我应该在函数退出之前调用指针上的delete,还是析构函数,这会在函数退出后自动调用,执行删除工作?

例如,

   void f()
   {
     A * a = new A(); // assume A has destructor defined, which frees any dynamically assigned resources
   }


 OR

  void f()
  {
    A * a = new A();
    delete a;
  }

删除和自动调用析构函数是否等效?

5 个答案:

答案 0 :(得分:9)

  

如果在一个函数中,我新建一个对象,我应该在函数退出之前调用指针上的delete,还是析构函数,这会在函数退出后自动调用,执行删除工作?

从函数返回时,所有具有自动存储持续时间的本地对象都将被销毁。如果它们是类类型,则在它们占用的存储被声明回来之前调用它们的析构函数。如果它们是非类类型(如int),则不会调用析构函数。

这里,唯一具有自动存储持续时间的本地对象是指针a(注意:不是a指向的对象!),指针不是类类型。这意味着a将被销毁,就是这样 - 特别是,对象a 指向的对象不会被销毁。

因此,您必须在离开函数之前调用delete(无论您是通过执行return还是抛出异常而离开它)。一般情况下,您始终需要将每次通话与new的来电匹配为delete,并且每次通过拨打new[]拨打delete[]

因为在用delete创建对象之后很容易忘记调用new(因为它很容易调用它!),所以在Modern C ++中使用它是一种很好的做法所谓的RAII包装器(例如智能指针),它们是本地对象,其析构函数用于清理构造期间获取的资源。

例如:

void foo()
{
    auto p = std::make_unique<A>(); // OK, make_unique() will only be available
                                    // in C++14. Meanwhile, in C++11 you can do:
                                    //
                                    // std::unique_ptr<A> p(new A());

    // Work with p...

    // No memory leak here!
}

如果你不被允许使用C ++ 11,例如因为你的老板说出于兼容性原因,SW必须在旧版本的编译器上编译,你总是可以杀死你的老板使用Boost的智能指针类,例如boost::shared_ptrboost::scoped_ptr

无论如何,请注意,除非您需要,否则不应执行动态分配。如果您不需要它(例如,如果您不必与任何其他函数共享该对象的所有权),您可以简单地为您的A对象提供自动存储持续时间,从而确保在以下时调用其析构函数它超出了范围:

void foo()
{
    A a;

    // Work with a...

    // a will be destroyed when returning from foo()
}

答案 1 :(得分:3)

只有自动对象超出范围时才会被销毁:

void f() {
    A a;
} // destroyed here

如果您使用new动态分配对象,则您有责任使用delete解除分配对象;否则,它将永远分配,你会泄漏内存。这可能非常难以正确管理,特别是如果异常可能导致您离开指针的范围。

出于这个原因,除非你真的需要,否则不要使用new;并始终使用共享指针或其他RAII对象来管理动态对象。

答案 2 :(得分:1)

唯一可以释放的是指针变量本身(因为它还需要内存来存储它指向的地址,并且其范围仅在函数体中)。指针指向的对象完全由您负责,因此您应该在显式分配时明确删除它。

答案 3 :(得分:1)

当您动态分配内存时,如果变量超出范围,则不会释放内存。你必须明确delete那个记忆。

答案 4 :(得分:0)

我将从此开始,

什么时候是一个名为?

的构造函数

创建(构建)对象时。 MyClass c,d(1);等。

构造函数用于在使用之前正确初始化对象。 分配必要的动态内存等。

什么时候是析构函数?

当一个对象超出范围时(当你遇到声明了该对象的}大括号时)。 当对象超出范围时,会自动调用析构函数。

动态分配内存(new)时, 它一直持续到你明确释放(delete)它。什么比构造函数更好,以确保你想要发生的*事情*。  因为,在对象被销毁之前,保证要析构析构函数,你可以在其上调用delete

默认情况下,析构函数不会清除您可能在代码中创建的副作用。它不会为你释放记忆。

你知道你的管家会跟着你走出房间。并且只会做你要求他做的事情。如果你指示他,他会在你离开后清理你的桌子。如果你不指示他这样做,你必须确保你自己在某个地方做到这一点或者只是留下一团糟

相关问题