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

Vin*_*rta 0 c++

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

ManagedFile mf("e.txt") //fails and throws
mf.F( //What would happen here?9
Run Code Online (Sandbox Code Playgroud)

永远不会被创造出来吗?

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

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

Bri*_*ian 7

如果建造mf失败,则的寿命mf将不会被认为是已经开始,任何部分结构mf将还原(通过调用已完成它们的结构的基础和成员的析构函数),和下面的行,在其中mf使用,将不会到达,因为控制将被转移到一个catch块(或程序将终止).


Sam*_*hik 5

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

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

对于任何超类也是如此。然后,抛出的异常还将销毁在开始构造子类之前构造的所有超类,并进入其构造函数,在该构造函数中抛出异常。

底线是对象被精心解构,也就是说,无论它的任何部分已经被构造,它们都会被解构。

最终,该对象不可能存在于任何地方。从逻辑上讲它不可能存在。

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

即使你捕获了异常:

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

       /* More code */
 } catch (...)
 {
     /* More code */
 }
Run Code Online (Sandbox Code Playgroud)

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

并且这个ManagedFile对象只存在于try块内部。在块之外try它不存在。这包括catch块。那里也不存在。

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

PS 如果对象是在动态范围内构造的(使用new),则抛出的异常还将负责释放由 分配的内存new,然后异常会向上传播。