1

bad_alloc在构造函数中抛出异常时,其中创建了多个对象,必须做什么来清理内存。前任。

class Object
{
   private:
     A * a;
     B  * b;

 public:

   Object()
   {
       a= new A();
       b= new B(); //So if a bad_alloc is called here, how is a deleted???
   }
} 

我的直觉是将每次调用 new 放在一个单独的 try catch 块中,并删除new之前调用的所有对象,但这太冗长了(第一个尝试块调用没有析构函数,第二个类调用第一个,第三个调用前两个等)。我的问题是:处理这个问题的最常见方法是什么?

另外,假设类对象包含一个不是用 new 创建的对象(因为它在堆栈上),它的析构函数会自动调用吗?

4

2 回答 2

6

您想使用智能指针:

class Object {
    std::unique_ptr<A> a;
    std::unique_ptr<B> b;

public:
    Object() : a(make_unique<A>()), b(make_unique<B>()) {}
}
于 2014-09-18T16:55:09.253 回答
2

首先我修复了你的代码,因为它是一个 C++ 问题,所以它必须写成 C++。构造函数可能会因 bad_alloc 以外的异常而失败。

您的选择在那里:

  • 不要存储指针而是存储对象。这些是自动构建的(或通过初始化列表),如果创建,yes 将自动清理。这可能会更好,但意味着它们需要完全定义,即包括它们的标题,并且您可能试图隐藏您的实现细节/解耦..

  • 存储某种智能指针,例如unique_ptr它实际上是一个对象,因此像对象一样被清理,如果存在则删除底层指针。

  • 在您的类中存储一个常规指针,但在构造函数期间使用unique_ptr(或者auto_ptr如果unique_ptr不可用),最后当您知道所有内容都已正确构造时,您可以将智能指针释放到您的成员变量中。

后一种解决方案如下所示:

 // header file
 //
class A; // implementation hidden on purpose
class B; // ditto

class Object
{
   private:
      A * a;
      B * b;

   public:
     Object();
     ~Object();

    private:

 // if not using C++11 do not put in =delete but still declare these

    Object( const Object & ) = delete;
    Object& operator=( const Object & ) = delete;

};

// cpp file

#include "object.h"
#include "a.h"
#include "b.h"

Object::Object()
   : a( nullptr ), // use NULL or 0 if nullptr not available
     b( nullptr )
{
    std::unique_ptr< A > pa( new A ); // might throw
    std::unique_ptr< B > pb( new B ); // might throw (1)

    a = pa.release(); // cannot throw
    b = pb.release(); 
}

Object::~Object()
{
     delete b;
     delete a;
}

(1) 如果它抛出pawhich is local 将调用其析构函数,这将删除您使用 new 创建的指针。

注意:如果您没有unique_ptr可用的,auto_ptr也可以在这里提供。

于 2014-09-19T11:46:02.920 回答