我有一个函数foo
可以抛出bar
例外。
在另一个函数中,我调用了foo
,但是如果抛出,我可以向bar
异常添加更多细节。 (我宁愿不将这些信息作为参数传递给foo
,因为它不属于那里,因为该函数的通用性质。)
所以我在调用者中执行此操作:
try {
foo();
} catch (bar& ex){
ex.addSomeMoreInformation(...);
throw;
}
throw
会重新抛出修改过的异常,还是需要使用throw ex;
?后者可能会采用有价值的副本,所以我宁愿不这样做。 throw
也会获取价值副本吗?我怀疑它不会。
(我知道我可以验证,但我担心会遇到一个未指定或未定义的构造,因此我想知道这一点。)
答案 0 :(得分:58)
实际上,这里的标准非常精确。 [except.handle] / 17:
当处理程序声明对非常量对象的引用时, any 对引用对象的更改是对临时对象的更改 执行 throw-expression 时初始化并且将具有 效果应该重新抛出该物体。
和[except.throw] / 8:
没有操作数的 throw-expression 重新抛出当前处理的内容 例外(15.3)。
答案 1 :(得分:27)
C ++11§15.1/ 8:
“ throw-expression 没有操作数会重新抛出当前处理的异常(15.3)。例外是 用现有的临时重新激活;没有创建新的临时异常对象。
答案 2 :(得分:3)
throw
(没有异常对象)将重新抛出当前异常。 (必须在catch块内,否则调用std::terminate)。因为您更改了当前异常对象的引用,所以您不需要使用explicilty抛出该对象,并且抛出重新抛出修改后的异常,并且不会创建新的临时对象。
答案 3 :(得分:3)
在这种情况下,您应该使用throw
来获得所需的行为...即,抛出将抛出修改后的异常,因为引用捕获了异常。
让我试着通过例子明确区分它们: -
class exception
{
};
class MyException : public exception
{
};
void func()
{
try
{
throw MyException();
}
catch( exception& e )
{
//do some modification.
throw; //Statement_1
throw e; //Statement_2
}
}
Statment_1: -
抛出的是它只是重新抛出当前的异常,即它不会进行进一步的复制(就像最初抛出异常时所做的那样)。因此,如果您在此处对捕获的异常进行任何更改...它也会出现在调用程序例程中。
Statement_2: -
这是抛出最初被捕获为MyException的“异常”,即它会再次复制。所以,只要忘记你所做的改变甚至不会传递给调用者或者*主要的异常。它会向调用者例程抛出“异常”。
希望我很清楚(并且正确地遵循C ++标准)足够......
答案 4 :(得分:2)
根据this,在c ++中抛出异常可以通过两种方式完成:
所以为了强调我的答案, throw 应该没问题。