8

このコード:

#include <iostream>
#include <stdexcept>

using namespace std;

int throw_it() {
  throw range_error( "foo" );
}

int main() {
  try {
    throw throw_it();
  }
  catch ( exception const &e ) {
    cerr << e.what() << endl;
    return 0;
  }
}

実行時に出力fooされますが、そうすることが保証されていますか? より具体的には、例外をスローするプロセス中に例外をスローすると、定義された動作が発生しますか? そして、その動作は最近スローされた例外をスローするものですか (上記のテスト コードのように)?

ご参考までに:

$ g++ --version
i686-apple-darwin11-llvm-g++-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)
4

2 に答える 2

15

一度に評価できる例外は 1 つだけです。15.1/7より

例外処理メカニズムが、スローされる式の評価を完了した後、例外がキャッチされる前に、例外によって終了する関数を呼び出す場合、std::terminate が呼び出されます。

あなたの例std::terminate()では、実際にスローされる例外は 1 つだけであるため、呼び出されません。にthrow throw_it();達すると、throw_it()最初に評価され、例外が実際にスローされる前に関数が呼び出されます。関数は例外をスローし、決して返さないため、元throwに到達することはありません。throw_it()例外をスローせずに整数値を返した場合、呼び出し元のスロー式が実行されます。あなたの例fooでは、印刷されることが保証されています。

しかし、アクティブなハンドラー内から新しい例外をスローする場合はどうでしょうか? 例外がキャッチされると、完全に評価されます。(「throw;」で再スローするのではなく) 新しい例外をスローすると、元の例外は破棄され、新しい例外の評価が開始されます。

15.1/4から

例外オブジェクトは、例外の最後に残っているアクティブなハンドラーが再スロー以外の方法で終了した後、または....

これは、一度に評価できる例外は 1 つだけであるという規則を満たします。

于 2013-05-29T02:00:45.003 に答える
3

より具体的には、例外をスローするプロセス中に例外をスローすると、定義された動作が発生しますか?

例外オブジェクトを構築した後、それをキャッチする前でstd::terminateなければ問題ありません。あなたの例では、例外オブジェクトはまったく作成されていないため、スローされるものは何もなく、代わりrange_error("foo")にスローされます。これはキャッチされる例外です。

これは次の方法で検査できます。

int throw_it() {
    throw range_error( "foo" );
    return 19;
}

int main() {
    try {
        try { // nested try is perfectly legal
            throw throw_it();
        } catch (...) {
            cerr << "not good!";
        }
    } catch (exception const &e) {
        cerr << e.what() << endl;
        return 0;
    }
}

出力:

not good!

RUN SUCCESSFUL (total time: 59ms)
于 2013-05-29T02:07:26.587 に答える