如果RAII构造函数抛出怎么办?

时间:2017-01-06 02:14:16

标签: c++

假设我有一个用于fopen的RAII类和一个名为ManagedFile的fclose,由于某种原因它失败并且构造函数抛出。

ManagedFile mf("e.txt") //fails and throws
mf.F( //What would happen here?9

永远不会创建吗?

如果它不会,如果我以后使用mf会发生什么,假设在mf中访问文件* F?

如果RAII类的构造函数失败,究竟会发生什么?

2 个答案:

答案 0 :(得分:7)

如果mf的构造失败,那么mf的生命周期将不会被认为已经开始,mf的任何部分构造将被还原(通过调用基础的析构函数)和已完成构建的成员),以及使用mf的以下行将无法到达,因为控制权将转移到catch块(或程序将终止)。

答案 1 :(得分:4)

如果构造函数抛出(并且构造函数本身未捕获抛出的异常),则对象的构造将失败。

如果类具有类成员,那么这些类成员将在构造函数执行之前完全构造,抛出的异常将在抛出的异常继续之前销毁它们。

同样适用于任何超类。抛出的异常将破坏在开始构造子类之前构造的任何超类,并进入其构造函数,抛出异常。

最重要的是,对象被精心解构,也就是说,无论它已经构建了什么部分,它们都会被解构。

最后,对象不可能存在于任何地方。它在逻辑上不可能存在。

由于未捕获异常,因此异常必须传播,并退出声明对象的作用域。

即使你发现异常:

 try
 {
       ManagedFile mf (  /* construct arguments */ );

       /* More code */
 } catch (...)
 {
     /* More code */
 }

这是您可能捕获异常的最早的地方。如果它被ManagedFile的构造函数抛出,则执行不能在try块内继续执行。你必须抓住异常,这是最快的,你可以抓住它。

ManagedFile对象仅存在于try块内。在try区块之外,它不存在。这包括catch块。它也不存在。

因此,如果此构造函数抛出异常,则该对象在逻辑上不可能存在。

P.S。如果对象是在动态作用域中构造的(使用new),抛出的异常也会在异常传播到梯形图之前释放由new分配的内存。