如果在构造函数中抛出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创建的对象(因为它在栈中),它的析构函数是自动调用的吗?
答案 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
也可以在此处投放。