关于捕获异常的最佳实践

15
我正在使用C++11编写一个小程序,并在第一次尝试中真正使用异常。我有一个关于如何高效地捕获异常的问题,在搜索了一些资料之后,仍然没有找到答案。
问题是: 通过(const?)左值引用捕获异常和通过(const?)右值引用捕获异常哪种更有效(或推荐)?
在代码中,这样写:
1)
try { throw std::exception{"what"}; }
catch (std::exception& ex) {}

2)

try { throw std::exception{"what"}; }
catch (const std::exception& ex) {}

3)

try { throw std::exception{"what"}; }
catch (std::exception&& ex) {}

4)

try { throw std::exception{"what"}; }
catch (const std::exception&& ex) {}

1
捕获rvalue引用甚至是非法的。https://dev59.com/pHzaa4cB1Zd3GeqPVNrP - anton_rh
2个回答

32

你应该使用const左值引用来捕获(2):

try { throw std::exception{"what"}; }
catch (const std::exception& ex) {}

缘由:

C++11中,通过使用shared_future,两个线程可能同时取消同一个异常。即使您没有意识到正在使用shared_future,除非您控制整个应用程序,否则在您的代码中仍可能发生这种情况。

如果两个线程同时捕获并取消同一个异常,并且其中一个或两个线程修改了异常,那么就会出现竞争条件。

因此,只要您不必在catch子句中修改异常对象,请让编译器为您强制执行该策略-通过const&进行捕获。如果您确实需要修改异常,则复制它,修改副本并抛出副本。如果您确定这不会切片异常对象(如果您捕获std::exception通常不是这种情况),则可以通过值捕获来完成此操作。


1

我认为异常应该通过左值引用通常方式来捕获。这里有使用右值引用的好解释。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接