在构造函数的成员初始化器列表中使用new

时间:2013-02-04 06:53:54

标签: c++

这编译,但我从未在任何其他代码中看到它。这样安全吗?

Testclass():sources(new int[32]){}

而不是:

Testclass(){
    sources = new int[32];
}

2 个答案:

答案 0 :(得分:10)

使用:

Testclass():sources(new int[32]){}

这是使用member-initialization-list,这是初始化成员的首选方式。

通过“安全”或“好”你可能意味着,它是否是例外安全的?如果new抛出bad_alloc异常怎么办?

那么,在这种情况下,析构函数将被调用,因为该对象没有完全构造,因为没有执行构造函数体。如果您已在初始化列表中获取任何资源,则可能存在资源泄漏。

考虑一下,

class X
{
    int  *ints;  // Order of declaration matters!
    Huge *huges; // It ensures that huges will be initialized after ints

    X() : ints(new int[32]), huges(new Huge[10000]) {}
};

如果new Huge[10000]抛出异常,分配给ints的内存将泄漏!

在这种情况下,function-try-block可能很有用。见这些:

如果你想到这个异常安全问题,你很快就会意识到如果一个班级只管理一个资源,那么生活会更容易。如果一个类管理多个资源,那么您将无法确定哪个在构件初始化列表中引发了异常,因此,您将无法决定在哪个资源中取消分配function-try-block的catch块。资源泄漏是注定的。

但是,如果一个类需要多个资源,那么首先将每个不同的类型资源封装在一个类中,并将这些资源管理类的对象声明为您的成员类。

答案 1 :(得分:0)

如果您使用奇怪的C ++语法在构造函数的初始化列表中使用try / catch块,那没关系:

class C {
    int *n;
public:
    C();
};

C::C()
try : n(new int[100])
{
  // do stuff here
}
catch(...)
{
  // handle exceptions
}

int main()
{
    C c; // Should be safe...
}