偶然見つけたコードを見ながら:
throw /*-->*/new std::exception ("//...
ここでnew
を使用する必要はない/使用すべきでないといつも思っていました。
正しい方法は何ですか、両方とも大丈夫ですが、そうであれば違いはありますか?
ところで、PowerShell Boostライブラリで「グレッピング」しているときに見ることができるものから、throw new
を使用することはありません。
追伸また、throw gcnew
を使用するCLIコードを見つけました。それは大丈夫ですか?
例外をスローおよびキャッチする従来の方法は、例外オブジェクトをスローし、参照(通常はconst
参照)によってキャッチすることです。 C++言語では、コンパイラが適切なコードを生成して例外オブジェクトを構築し、適切なタイミングで適切にクリーンアップする必要があります。
動的に割り当てられたオブジェクトへのポインタを投げることは、決して良い考えではありません。例外を使用すると、エラー状態に直面しても、より堅牢なコードを作成できます。従来の方法で例外オブジェクトをスローすると、catch (...)
によって正しい型を指定するcatch句でキャッチされるかどうか、その後再スローされるかどうかを確認できます。適切なタイミングで正しく破壊されました。 (唯一の例外は、まったくキャッチされない場合ですが、これはあなたがどのように見ても回復不可能な状況です。)
動的に割り当てられたオブジェクトへのポインターをスローする場合、例外をスローしたい時点で呼び出しスタックがどのようなものであっても、正しいポインター型を指定し、適切なdelete
呼び出し。そのブロックが例外を再スローしない限り、catch (...)
で例外をキャッチしてはなりません。例外は、例外を正しく処理する別のcatchブロックでキャッチされます。
事実上、これは、堅牢なコードを記述しやすくし、すべての状況で正しいコードを記述するのを非常に困難にする例外処理機能を採用したことを意味します。これにより、この機能を想定していないクライアントコードのライブラリコードとして機能することはほとんど不可能になるという問題がなくなります。
例外をスローするときにnew
を使用する必要はありません。
書くだけ:
throw yourexception(yourmessage);
としてキャッチ:
catch(yourexception const & e)
{
//your code (probably logging related code)
}
yourexception
はstd::exception
から直接または間接的に派生することに注意してください。
呼び出しサイトがnew std::exception
をキャッチすることを期待している場合、std::exception*
を投げることは正しいです。しかし、例外へのポインタをキャッチすることを期待する人はいません。それがあなたの関数が行うことを文書化し、人々が文書を読んだとしても、彼らはまだ忘れて、代わりにstd::exception
オブジェクトへの参照をキャッチしようとする傾向があります。
C++ FAQでこれに関する素晴らしい議論があります:
基本的に「参照しないでキャッチする正当な理由がない限り、参照によるキャッチ。値によるキャッチは避けてください。コピーが行われ、コピーはスローされたものと異なる動作をする可能性があります。 」