tryブロック
例外は、try ブロック内でスローされた場合、関連するハンドラによって処理される可能性があります。
目次 |
[編集] 構文
try 複合ステートメント ハンドラ列 |
(1) | ||||||||
try ctor-initializer (オプション) 複合ステートメント ハンドラ列 |
(2) | ||||||||
| compound-statement | - | a 複合ステートメント |
| ハンドラ列 | - | 非空のハンドラのシーケンス |
| ctor-initializer | - | メンバ初期化子リスト(コンストラクタのみ) |
[編集] 通常の try ブロック
通常の try ブロックはステートメントです。
その 複合ステートメント から例外がスローされた場合、その例外は ハンドラ列 の ハンドラ と照合されます。
void f() { throw 1; // NOT handled by the handler below try { throw 2; // handled by the associated handler } catch (...) { // handles the exception 2 } throw 3; // NOT handled by the handler above }
[編集] 関数 try ブロック
関数 try ブロックは、特殊な種類の関数本体です。
その 複合ステートメント または ctor-initializer (もしあれば) から例外がスローされた場合、その例外は ハンドラ列 の ハンドラ と照合されます。
int f(bool cond) { if (cond) throw 1; return 0; } struct X { int mem; X() try : mem(f(true)) {} catch (...) { // handles the exception 1 } X(int) try { throw 2; } catch (...) { // handles the exception 2 } };
静的記憶域期間を持つオブジェクトのデストラクタ、または静的記憶域期間を持つ非ブロック変数に関連付けられたオブジェクトのコンストラクタでスローされた例外は、main 関数上の関数 try ブロックによって捕捉されません。
|
スレッド記憶域期間を持つオブジェクトのデストラクタ、またはスレッド記憶域期間を持つ非ブロック変数に関連付けられたオブジェクトのコンストラクタでスローされた例外は、スレッドの初期関数上の関数 try ブロックによって捕捉されません。 |
(C++11以降) |
関数がコンストラクタまたはデストラクタでない限り(以下を参照)、関数 try ブロックの ハンドラ の 複合ステートメント の末尾を越えてフローすることは、その関数 try ブロックの 複合-ステートメント の末尾を越えてフローすることと同等です。
[編集] コンストラクタとデストラクタの try ブロック
クラス C の場合、そのコンストラクタまたはデストラクタ定義の関数本体が関数 try ブロックであり、C のサブオブジェクトの初期化または破棄中に例外がスローされた場合、その例外は関数 try ブロックの ハンドラ列 の ハンドラ とも照合されます。
int f(bool cond = true) { if (cond) throw 1; return 0; } struct X { int mem = f(); ~X() { throw 2; } }; struct Y { X mem; Y() try {} catch (...) { // handles the exception 1 } ~Y() try {} catch (...) { // handles the exception 2 } };
コンストラクタまたはデストラクタの関数 try ブロックのハンドラ内で、そのオブジェクトの非静的メンバまたは基底クラスを参照すると、未定義の動作になります。
コンストラクタの関数 try ブロックのハンドラ内に return ステートメント が現れた場合、プログラムは不正です。
コンストラクタまたはデストラクタの関数 try ブロックのハンドラの末尾に制御が達した場合、現在処理中の例外が再スローされます。
[編集] 制御フロー
try ブロックの 複合ステートメント は、制御フロー制限付きステートメントです。
void f() { goto label; // error try { goto label; // OK label: ; } catch (...) { goto label; // error } }
ジャンプステートメント(goto、break、return、continue)は、try ブロック(そのハンドラを含む)から制御を転送するために使用できます。この場合、try ブロック内で宣言された各変数は、その宣言を直接含むコンテキストで破棄されます。
try { T1 t1; try { T2 t2; goto label; // destroy t2 first, then t1 } catch(...) { // executed if an exception is thrown while destroying t2 } } catch(...) { // executed if an exception is thrown while destroying t1 } label: ;
[編集] キーワード
[編集] 欠陥報告
以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| CWG 98 | C++98 | switch ステートメントは制御を転送できます。 try ブロックの 複合ステートメント 内へ |
禁止された |
| CWG 1167 | C++98 | デストラクタ上の関数 try ブロックが 基底またはメンバデストラクタからの例外を捕捉するかどうかは未指定でした。 |
そのような例外 は捕捉されます |