C ++ bad_alloc在构造函数中抛出

时间:2014-09-18 16:50:25

标签: c++ exception constructor bad-alloc

如果在构造函数中抛出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???
   }
} 

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

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

2 个答案:

答案 0 :(得分:6)

您想使用智能指针:

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

public:
    Object() : a(make_unique<A>()), b(make_unique<B>()) {}
}

答案 1 :(得分:2)

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

你的选择是:

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

  • 存储某种智能指针,例如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)如果它抛出pa本地将调用它的析构函数,这将删除你用new创建的指针。

注意:如果您没有unique_ptr可用,auto_ptr也可以在此处投放。