在更有效的c++第13项中,第13项:通过引用捕获异常。
还有一点要说——要通过指向工作的指针捕获异常,程序员必须以确保控件离开函数后对象存在的方式定义异常对象。全局对象和静态对象工作正常。
//通过指针捕获异常的示例
class exception { ... }; // from the standard C++
void someFunction()
{
static exception ex; // exception object
...
throw &ex; // throw a pointer to ex
...
}
void doSomething()
{
try
{
someFunction(); // may throw an exception*
}
catch (exception *ex)
{ // catches the exception*;
... // no object is copied
}
}
我的疑问是,在通过引用捕获异常的情况下,它有什么不同?若它是一个局部变量(不是静态的或全局的),那个么一旦控件离开函数,对象就不存在了。那么如何通过引用捕获异常来解决这个问题呢?
要捕获指针,必须抛出一个指针。若要捕获引用,请按值抛出对象。给定对象名称的throw表达式生成对象的副本;它不会将其论点解释为引用。
抛出的副本被称为异常对象,它位于运行库维护的特殊分配区域中。它的析构函数在异常传播完成时被调用,异常传播可能在调用堆栈的任何位置。C++11提供了额外的工具,可以使用引用计数语义手动控制异常对象的生存期。
如果按值捕获,则在进入按值捕获的catch
块时会生成另一个副本,并且在离开该catch
块时会销毁第二个副本,即使异常传播到另一个封闭的catch
块。外部catch
将在没有由内部catch
应用任何修改的情况下看到原始异常对象。
通过非const
引用捕获的习惯用法实现了让catch
块通信的能力。
顺便说一句,由于指针抛出无法处理内存不足的错误,因此它从根本上被破坏了。如果尝试使用new
分配异常对象,但没有更多内存,则std::bad_alloc
将在程序到达throw
表达式之前劫持程序。该库提供了一种分配异常的替代方法,以应对内存不足的情况。