构造函数中的异常

时间:2015-07-01 04:27:56

标签: c++ destructor

考虑以下课程:

struct A
{
    A(){ std::cout << "A()" << std::endl; throw std::exception(); }
    ~A(){ std::cout << "~A()" << std::endl; }
};

A a;
int main(){ }

DEMO

标准承诺将调用适当的释放函数N4296::5.3.4/20 [expr.new]

  

如果上述对象初始化的任何部分78终止   通过抛出异常,已经获得了对象的存储,   并且可以找到合适的解除分配函数,即释放   调用函数来释放对象所在的内存   构造

但是析构函数呢?在那个例子中没有被召唤。那么,我们得到了UB吗?

2 个答案:

答案 0 :(得分:2)

为所有成功初始化的对象调用析构函数。

否则必须进行默认的零初始化(一些开销),以便能够在析构函数中假设任何内容。

构造函数抛出的A对象未成功初始化。所以它的析构函数没有被执行。但是,如果它具有在异常之前已成功初始化的任何类类型子对象(基类子对象,数据成员),则会为这些子对象调用析构函数。

不,从构造函数中抛出的不是UB。

相反,它是信令构造失败的常见方式,它确保调用者要么具有成功初始化且可能是可用的对象,要么(只是)异常。

历史。最初C ++没有例外。然后通过将0分配给this来表示施工失败。我不记得它是如何与分配相互作用的,但可能与异常现在的方式相同,即保证解除分配。但是使用这种方案,你只能为动态分配的对象构建失败......

答案 1 :(得分:0)

析构函数与解除分配器不同。每当变量超出范围时,将删除引用该变量的对象。在你给出的问题中,对象是一个全局变量,所以当程序终止时它将被删除。