在构造函数成员初始化器中抛出C ++异常?

时间:2013-01-06 22:01:05

标签: c++ exception c++11 constructor

考虑以下情况:

struct X { ... };

struct Y
{
     Y(...);

     ...

     X x;

     ...
}

X f()
{
    ...

    if (...)
        throw E;

    ...
}

Y::Y(...) :
    ... ,
    x(f()) ,
    ...
{
    ...
}

这里有未定义的行为吗?当抛出E时,这种设计是否存在任何问题或潜在问题?

更新

Y::x可能不是Y的唯一成员变量,可能不是类中的第一个成员变量,可能会在Y::Y初始化列表的一半初始化。< / p>

2 个答案:

答案 0 :(得分:5)

  

这里有未定义的行为吗?

没有。 Y的构造已中止。

  

当抛出E时,这种设计是否存在任何问题或潜在问题?

永远不会创建Y,因此没有析构函数可以调用。完全构造的元素的析构函数,即在类体中x之前声明的元素,将被自动调用(否则你怎么知道它抛出时的初始化列表有多远)。如果你需要销毁任何东西,那么你必须抓住异常并自行销毁它。你不能吸收异常,你可以重新抛出它,抛出一个新的异常,或者什么都不做会导致异常被重新抛出。对于您的特定用例,不应该有任何可以破坏的内容,因为根本不会调用构造函数体。

答案 1 :(得分:2)

当在构造对象期间抛出异常时,将调用所有完全构造的子对象的析构函数。也就是说,假设您的类型X正确地抛出异常,清除它在抛出异常之前可能已分配的任何资源,则没有问题。