为什么捕获异常作为对const的引用?


84

我听说过很多次,最好将异常捕获为对const的引用而不是引用。为什么是:

try {
    // stuff
} catch (const std::exception& e) {
    // stuff
}

优于:

try {
    // stuff
} catch (std::exception& e) {
    // stuff
}

Answers:


67

你需要:

  • 引用,以便您可以多态访问异常
  • 一个const以提高性能,并告诉编译器您不会修改该对象

后者不像前者那么重要,但是删除const的唯一真正原因是发出信号,表明您想对异常进行更改(通常仅在您希望将其添加到更高级别的上下文中重新抛出该异常时才有用) 。


1
“告诉编译器您不打算修改对象” —我想如果要将对象作为参数传递给函数调用,这可能会很有用。
Craig McQueen 2013年

1
“多态访问异常”是什么意思?
芒果

3
@mango大概意味着它能够调用虚拟函数(例如std::exceptionwhat()函数)。如果按值捕获,则无法调用该函数并获取原始异常详细信息。
MM

11
考察了由Apple clang 7和gcc 5(带有优化O3)生成的程序集,我没有看到const ref和non-const ref程序集之间没有任何区别。因此,我认为gcc和苹果
罐的

2
编译器可以轻松查看您修改了哪些对象,而没有修改(SSA和恒定传播)。需要更好的解释(或者是神话吗?)。
rustyx

31

根本没有理由。

异常对象生活在自己的内存空间所以您不必到大约醒目的临时表达式创建的异常担心。

您所做的一切都是保证您不会修改异常对象,但是由于异常对象应该具有不可变的接口,因此这里实际上没有任何实际意义。

但是,当您阅读它时,可能会让您感到温暖和舒适-这就是我的感受!

它们具有自己的特殊线程本地堆栈。
免责声明: Boost.Exception破坏了此功能,以便进行时髦的操作并在构造后添加异常详细信息。但这是黑客!


您能详细说明一下Exception objects live in their own memory space吗?您是否对此有很好的建议?
理查德·达利

@LeFlou:我可以为您指出标准,但是认为“不错的读物”会有点误导...:P
Lightness Races in Orbit

绝对可以,从标准的角度了解更多有关此的知识将很有趣。我正在阅读有关C ++性能的技术报告,您是否有更相关的文档?
理查德·达利

@LeFlou:嗯,它不会得到任何比标准本身更具权威性....
在轨道亮度赛

1
@RichardDally检查C ++ Primer 5th,第18.1.1节执行对象。它说异常对象驻留在由编译器管理的空间中,可以保证无论调用哪种catch都可以访问该异常对象。完全处理完异常后,异常对象将被销毁。
瑞克(Rick)

5

它告诉编译器您不会调用任何修改异常的函数,这可能有助于优化代码。可能并没有太大的区别,但是这样做的成本也很小。


2

您要修改例外吗?如果不是,则可能是const。同样的原因,您应该在其他任何地方使用const(我说应该,因为它实际上并没有在表面上产生太大的改变,可以帮助编译器,还可以帮助编码人员正确使用您的代码,而不做他们不应该做的事情)

异常处理程序,可能是特定于平台的,并且可能将异常放在有趣的地方,因为他们不希望它们发生变化?


-1

出于相同的原因,您使用了const。


出于与为什么偏爱指针而不是引用的原因相同:-)
Dimitri C.

12
简单而轻松,但并不是真正的答案。
2010年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.