是否应该例外

时间:2014-01-16 00:13:37

标签: c++ exception exception-handling

毫无疑问,异常是有用的,因为它们向程序员显示他正在使用错误的函数或者在环境中发生了不好的事情,但是真的需要捕获它们吗?

未捕获异常正在终止程序,但您仍然可以看到问题所在。在设计良好的库中,每个“意外”情况实际上都有解决方法。例如,使用map::find而不是map::at,在使用索引运算符之前检查int变量是否小于vector::size

为什么有人需要这样做(不包括使用强制执行它的库的人)?基本上,如果您正在为给定的异常编写处理程序,那么您也可以编写一个阻止它发生的代码。

4 个答案:

答案 0 :(得分:6)

并非所有例外都是致命的。它们可能不常见,因此也可能是“异常”,但调用堆栈中的高点可以实现重试或继续。通过这种方式,异常用于展开堆栈和嵌套的一系列函数或方法调用程序中的一个点,它实际上可以处理异常的原因 - 即使只是为了清理一些资源,记录错误,并继续像往常一样。

答案 1 :(得分:1)

您不能总是编写能够防止异常的代码。仅举一个明显的例子,考虑并发代码。假设我尝试验证i介于(比如说)0和20之间,然后使用i索引到某个数组。所以,我检查并i == 12,所以我继续使用它来索引数组。不幸的是,在测试和索引操作之间,一些其他线程将{20}添加到i,因此当它被用作索引时,它不再在范围内。

并发导致竞争条件,因此尝试确保异常情况失败。虽然可能通过(例如)将每个这样的测试/使用序列包装在关键部分(或类似部分)来防止这种情况,但这样做通常是不切实际的 - 首先,通常会获得正确的代码非常困难,其次即使你确实这样做,对执行速度的影响可能是不可接受的。

异常还会将检测异常条件的代码与做出反应的代码分离到该异常情况。这就是为什么异常处理如此受到库编写者的欢迎。库中的代码没有关于对特定异常情况作出反应的正确方法的线索。仅仅是一个非常简单的例子,我们假设它无法从文件中读取。是否应该向stderr打印消息,弹出MessageBox或写入日志?

实际上,它不应该做这些。对于任何给定的程序,至少两个(可能全部三个)都是错误的。因此,它应该做的是抛出异常,让更高级别的代码确定适当的响应方式。对于一个程序,记录错误并继续其他工作可能是有意义的,但对于另一个程序,该文件可能足够关键,其唯一合理的反应是完全中止执行。

答案 2 :(得分:0)

异常是非常昂贵的,性能差异 - 因此,无论何时性能问题,您都需要编写一个免除异常的代码(使用“普通C”技术进行错误传播)。

但是,如果性能不是直接关注的话,那么异常将允许您开发一个不那么混乱的代码,因为可以推迟错误处理(但是那时你将不得不处理非本地控制转移,这可能是令人困惑的是。)

答案 3 :(得分:0)

我使用了大量例外作为根据事件处理转移对特定位置的控制的方法。 例外也可以是将控制转移到调用函数树的“标记”位置的方法。 当异常发生时,代码可能被认为是一次回溯一个级别并检查该级别是否有异常并执行它。

异常的真正问题是你真的不知道这些会发生在哪里。 到达异常的代码通常不知道为什么会出现问题,因此快速返回已知状态是一个很好的操作。 让我们举一个例子:你在威尼斯,看着地图走过小路,你到达的地方就是你无法在地图中找到的地方。 基本上你很困惑,你不明白你在哪里。 如果您有ariadne“μιτος”,您可以返回已知点并重新启动以尝试到达您想要的位置。

我认为您应该将错误处理仅视为一种控制结构,允许在任何级别上返回(通过错误处理例程和错误代码)。