64

我已经读到使用 C++ 异常进行异常处理有一些开销,而不是检查返回值。我只是在谈论没有抛出异常时产生的开销。我还假设您需要实现实际检查返回值并执行适当操作的代码,无论这与 catch 块所做的操作等效。而且,将抛出异常对象的代码与内部包含 45 个状态变量的代码与为每个错误返回负整数的代码进行比较也是不公平的。

我并不是仅仅基于可能执行得更快的 C++ 异常来建立一个案例来支持或反对 C++ 异常。我最近听说有人提出,一旦您考虑到检查返回值和处理错误所需的所有额外簿记代码,使用异常的代码应该与基于返回码的代码一样快地运行。我错过了什么?

4

6 回答 6

56

某些平台和某些编译器上,异常处理需要付出一定的代价。

即,Visual Studio 在构建 32 位目标时,将在每个具有非平凡析构函数的局部变量的函数中注册一个处理程序。基本上,它设置了一个try/finally处理程序。

gcc面向 64 位的 Visual Studio采用的另一种技术仅在引发异常时才会产生开销(该技术涉及遍历调用堆栈和表查找)。在很少抛出异常的情况下,这实际上可以产生更高效的代码,因为不必处理错误代码。

于 2009-12-13T22:15:17.230 回答
16

只有 try/catch 和 try/except 块需要一些指令来设置。除了最紧密的循环之外,开销通常在每种情况下都可以忽略不计。但是无论如何,您通常不会在内循环中使用 try/catch/except 。

我建议不要担心这一点,而是使用分析器在需要的地方优化你的代码。

于 2009-12-13T22:07:35.010 回答
11

它完全依赖于实现,但是当不抛出异常时,许多最近的实现几乎没有或没有性能开销。事实上你是对的。在不使用异常的代码中正确检查所有函数的返回码可能比对使用异常的代码不做任何事情要慢。

当然,您需要根据您的特定要求测量性能以确定。

于 2009-12-13T22:08:59.533 回答
1

有一些例外情况开销(正如其他答案指出的那样)。

但是现在你没有太多的选择。尝试在你的项目中禁用异常,并确保所有依赖的代码和库都可以在没有的情况下编译和运行。

他们是否在禁用异常的情况下工作?

让我们假设他们这样做!然后对某些情况进行基准测试,但请注意您必须设置“禁用异常”编译开关。如果没有那个开关,你仍然有开销——即使代码从不抛出异常。

于 2009-12-13T22:27:22.040 回答
0

唯一的开销是 ~6 条指令,它们在函数开头添加 2 个 SEH,并将它们留在末尾。无论线程中有多少次尝试/捕获,它总是相同的。

还有这关于局部变量是什么?我听到人们在使用 try/catch 时总是抱怨它们。我不明白,因为无论如何最终都会调用解构函数。此外,您不应该让异常上升超过 1-3 个电话。

于 2009-12-13T22:56:51.550 回答
-3

我拿了 Chip Uni 的测试代码并对其进行了一些扩展。我将代码分成两个源文件(一个有异常;一个没有)。我让每个基准测试运行 1000 次,并使用clock_gettime()withCLOCK_REALTIME记录每次迭代的开始和结束时间。然后我计算了数据的均值和方差。我使用 64 位版本的 g++ 5.2.0 和 clang++ 3.7.0 在具有 16GB RAM 的 Intel Core i7 机器上运行此测试,该机器运行带有内核 4.2.5-1-ARCH 的 ArchLinux。您可以在此处找到扩展代码和完整结果。

克++

没有例外
  • 平均:30,022,994 纳秒
  • 标准偏差:1.25327e+06 纳秒
例外
  • 平均:30,025,642 纳秒
  • 标准偏差:1.83422e+06 纳秒

铿锵++

没有例外
  • 平均:20,954,657 纳秒
  • 标准偏差:426,662 纳秒
例外
  • 平均:23,916,638 纳秒
  • 标准偏差:1.72583e+06 纳秒

使用 clang++ 时,C++ 异常只会导致不小的性能损失,即使这种损失也只有 ~14%。

于 2015-11-29T18:55:32.120 回答