3

別のメソッドで戻り値の代わりに例外をスローするライブラリ プロジェクトの 1 つに取り組んでいたときに、好奇心から生じた一般的な質問をしていますが、その例外を戻り値に変換したいと考えています。複数の try catch ブロックを使用して解決しましたが、C++ で例外がスローされた後に再開する方法があることを知りたいだけです。

4

3 に答える 3

6

私はあなたが何を望んでいるのか完全にはわかりません。例外を戻りコードに変換しても、例外の後で再開されません。C++ 委員会は再開を検討しましたが、それが何を意味するのかは明確ではありませんでした。検討:

int
someFunction()
{
    // ...
    if ( someCondition ) {
        throw SomeException();
    }
    assert( !someCondition );
    // ...
}

C++ では、assertがトリガーされることはありません (そして、と はアサートされた条件が後で有効であることを明確にするため、通常はそれを記述しません) ifthrow例外を再開できる場合は、assertwould (または少なくとも might) がトリガーされます。コード検証の重要な手段を失うことになります。

また、他の言語でそれを使用したことがある人は、実際にはうまく機能しないと報告しており、再開を使用し始めたすべてのケースで、後で使用しないようにコードを変更する必要がありました。

于 2013-09-19T08:24:58.800 に答える
2

いいえ。実際、コンパイラは、例外がスローされた後、到達不能なコードの命令を発行することさえできない場合があります。

throw std::invalid_argument;
int i = 5; // No instructions generated for this, as it is unreachable.
于 2013-09-19T08:20:38.907 に答える
0

resume安全に動作する命令を作成するには、 の直後でthrowはなく、その前の の直前にジャンプifして、条件を再テストする必要があります。

ここでの問題は、C++ の例外が考えられる方法によって、それらはステートメント自体であり、必ずしも即時の条件分岐ではないということです。(ifthrowは互いに独立して定義されます)

また、 と の間にthrow(catch外部でいくつかの関数呼び出しが含まれる場合があります)、「スタック アンローリング」という名前のものがあります。これは、すべてのローカルのすべてのデストラクタを実際に呼び出し、エスケープする必要があるブロックに残されます。" resume" はこれらすべてのオブジェクトを再構築する必要がありますが、そのようなデストラクタのアクションはスロー命令自体に依存せず、「元に戻せない」可能性があるため、システム状態を一貫して復元することはほとんど不可能です。

可能なイディオムは

for(;;)
{
   try
   {
     ... everything may throw ...
     break; //if you are here everything was successful, so stop looping and go on
   }
   catch(whatever_you_may)
   { 
      try_to_repair;
      if(impossible) throw;
   }
}

実際には、成功するか、そうではないと判断するまでループします。

ただし、これが再構築 (または非破壊) ではなく、再実行であることに注意してください。

于 2013-09-19T09:06:48.430 に答える