假设我有一个用于fopen的RAII类和一个名为ManagedFile的fclose,由于某种原因它失败并且构造函数抛出。
ManagedFile mf("e.txt") //fails and throws
mf.F( //What would happen here?9
永远不会创建吗?
如果它不会,如果我以后使用mf会发生什么,假设在mf中访问文件* F?
如果RAII类的构造函数失败,究竟会发生什么?
答案 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
分配的内存。