章节目录

第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结合使用,在具备强异常保证时使用移动语义(否则使用复制语义)。

最后,异常处理确实有成本。在大多数情况下,使用异常的代码会运行得稍慢一些,而且处理异常的成本非常高。您应该只使用异常来处理异常情况,而不是用于正常的错误处理场景(例如,判定用户的无效输入)。


27.9 std::move_if_noexcept

上一节

28.0 输入和输出(I/O)流

下一节


本节目录