我想问this question(也是here),但这次是关于C ++。
之间C ++的区别是什么
try { /*some code here*/}
catch(MyException& ex)
{ throw ex;} //not just throw
和
try { /*some code here*/}
catch(MyException& ex)
{ throw;} //not throw ex
它只是在堆栈跟踪中(在C ++中,在任何情况下都不是C#或Java中的标准)?
(如果有任何不同,我使用的是MSVS 2008.)
答案 0 :(得分:32)
throw;
重新抛出它在throw ex;
抛出新异常时捕获的同一异常对象。除了创建新异常对象的性能原因之外,它没有什么区别。如果你有一个异常层次结构,其中有一些其他异常类派生自MyException
类,并且在抛出异常时你已经完成throw DerivedClassException;
它可以被catch(MyException&)
捕获。现在,如果您修改此捕获的异常对象并使用throw;
重新抛出它,则异常对象的类型仍为DerivedClassException
。如果执行throw Ex;
,则会发生对象切片,并且新抛出的异常将为MyException
类型。
答案 1 :(得分:14)
[C++ FAQ Lite § 17.9]
throw;
(throw
关键字后面没有异常对象)是什么意思?我在哪里使用它?您可能会看到类似这样的代码:
class MyException { public: ... void addInfo(const std::string& info); ... }; void f() { try { ... } catch (MyException& e) { e.addInfo("f() failed"); throw; } }
在此示例中,语句
throw;
表示“重新抛出当前异常”。这里,函数捕获异常(通过非const引用),修改异常(通过向其添加信息),然后重新抛出异常。这个习惯用法可以通过在程序的重要函数中添加适当的catch子句来实现一种简单的堆栈跟踪形式。另一个重新抛出的习语是“例外调度员”:
void handleException() { try { throw; } catch (MyException& e) { ...code to handle MyException... } catch (YourException& e) { ...code to handle YourException... } } void f() { try { ...something that might throw... } catch (...) { handleException(); } }
这个习惯用法允许重复使用单个函数(
handleException()
)来处理许多其他函数中的异常。[C++ FAQ Lite § 17.11]当我抛出这个对象时,会被复制多少次?
取决于。可能是“零”。
抛出的对象必须具有可公开访问的复制构造函数。允许编译器生成任意次数复制抛出对象的代码,包括零。但是,即使编译器从未实际复制抛出的对象,它也必须确保异常类的复制构造函数存在且可访问。
(编辑以更清楚地说明我认为很明显...... )
catch(MyException& ex) { throw ex; }
可能会复制ex
及其带来的所有问题; catch(MyException& ex) { throw; }
可能不会。
答案 2 :(得分:12)
如果您有异常层次结构,throw ex
可以对您的例外进行切片,而throw
则不会。例如:
#include <iostream>
#include <string>
using namespace std;
struct base
{
virtual string who() {return "base";}
};
struct derived : public base
{
string who() {return "derived";}
};
int main() {
try {
try {
throw derived(); // throws a 'derived'
}
catch (base& ex)
{
throw ex; // slices 'derived' object to be a 'base' object
}
}
catch (base& ex)
{
cout<<ex.who()<<endl; // prints 'base'
}
}
将throw ex
更改为throw
,您将获得derived
的输出,这是您可能希望得到的。
答案 3 :(得分:5)
您可以将throw;
表单与catch(...)
一起使用(如果您使用了catch(...),这是重新抛出的唯一方法。)
答案 4 :(得分:3)
有很大的不同。我在我的博客上写了这篇文章:https://cpptalk.wordpress.com/2009/08/23/nuances-of-exception-rethrow/
非常欢迎您来看看
答案 5 :(得分:2)
throw ex
将制作另一个副本,不建议仅使用throw
来抛出当前的异常对象。
答案 6 :(得分:2)
throw可以抛出catch(...)捕获的非标准异常类型(例如结构化异常)
答案 7 :(得分:1)
此外,由于它有时会引起混淆,因此异常处理上下文之外的throw;
将会中止该程序。