foo
例外をスローできる関数bar
があります。
別の関数でfoo
を呼び出しますが、スローされた場合はbar
例外に詳細を追加することができます。 (その関数の一般的な性質のため、実際にはそこに属していないため、パラメーターなどの情報をfoo
に渡したくありません。)
だから私は発信者でこれを行います:
try {
foo();
} catch (bar& ex){
ex.addSomeMoreInformation(...);
throw;
}
throw
は変更された例外を再スローしますか、それともthrow ex;
を使用する必要がありますか?後者はおそらくバリューコピーを取るので、私はそれをしたくありません。 throw
も値のコピーを取りますか?そうではないと思います。
(確認できることは承知していますが、未指定または未定義の構成に遭遇することが心配なので、確実に知りたいと思います)。
C++11§15.1/ 8:
”オペランドのないthrow-expressionは、現在処理されている例外(15.3)を再スローします。例外は、既存の一時的なもので再アクティブ化されます。新しい一時例外オブジェクトは作成されません。
実際、ここでは標準が非常に正確です。 [except.handle]/17:
ハンドラーが非定数オブジェクトへの参照を宣言すると、参照されたオブジェクトへの変更は、throw-expressionが実行されたときに初期化された一時オブジェクトへの変更です。そのオブジェクトが再スローされた場合に効果があります。
そして[except.throw]/8:
オペランドのないthrow-expressionは、現在処理されている例外(15.3)を再スローします。
この場合、throw
を使用して目的の動作を取得する必要があります...つまり、例外が参照によってキャッチされたため、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としてキャッチされた「例外」をスローしています。つまり、コピーが再度作成されます。したがって、行った変更は、呼び出し元にor * ginal例外を渡さないことを忘れてください。呼び出し元ルーチンに「例外」をスローします。
私が十分に明確である(そしてC++標準のトラックで正しい)ことを願っています...
throw
(例外オブジェクトなし)は、現在の例外を再スローします。 (catchブロック内にある必要があります。そうでない場合、 std :: terminate が呼び出されます)。現在の例外オブジェクトの参照を変更したので、オブジェクトを明示的にスローする必要はなく、throwは変更された例外を再スローし、新しい一時オブジェクトはありませんオブジェクトが作成されます。
this によると、c ++で例外をスローするには、次の2つの方法があります。
したがって、私の答えを強調するために、throwはあなたの場合は問題ないはずです。