第27章总结
本节阅读量:异常处理提供了一种机制,可以将错误或其他异常情况的处理与代码的典型控制流解耦。这允许更自由地以最有用的时间和方式处理错误,减轻了返回码导致的许多混乱。
throw语句用于引发异常。Try块查找由在其中编写或调用的代码引发的异常。这些异常被路由到catch块,catch块捕获特定类型的异常(如果匹配)并处理它们。默认情况下,捕获的异常被视为已处理完成。
异常将立即处理。如果引发异常,控件流将跳到最近的封闭try块,查找可以处理该异常的catch处理程序。如果找到匹配的try/catch,则调用栈将展开到对应catch块的起点,并在匹配的catch的顶部恢复执行。如果找不到try块或没有匹配的catch块,程序将调用std::terminate,这将以未处理的异常错误结束程序执行。
可以抛出任何数据类型的异常,包括类。
Catch块可以配置为捕获特定数据类型的异常,或者可以使用省略号(…)设置捕获全部异常。捕获基类引用的catch块也将捕获派生类的异常。标准库抛出的所有异常都派生自std::exception类(位于exception 头文件中),因此通过引用捕获std::exception将捕获所有标准库异常。what()成员函数可用于确定引发了哪种类型的std::exception。
在catch块内部,可能会抛出新的异常。通过只使用关键字throw,可以从catch块重新抛出当前捕获的异常。不要使用捕获的异常变量重新抛出异常,否则可能会导致对象切片。
函数try块为您提供了一种捕获函数或关联的成员初始化列表中发生的任何异常的方法。它通常仅与派生类构造函数一起使用。
永远不要从析构函数中抛出异常。
noexcept异常说明符可用于表示函数没有抛出异常/不会失败。
如果对象具有noexcept-移动构造函数,则std::move_if_noexcept将返回可移动的右值,否则它将返回可复制的左值。我们可以将noexcept说明符与std::move_if_noexcept结合使用,以在具有强异常保证时使用移动语义(否则使用复制语义)。
最后,异常处理确实有成本。在大多数情况下,使用异常的代码将运行得稍微慢一些,并且处理异常的成本非常高。您应该仅使用异常来处理异常情况,而不是用于正常的错误处理情况(例如,判定用户的无效输入)。
