例外をキャッチするには3つの方法があることがわかりましたが、違いは何ですか?
1)値でキャッチ。
2)参照でキャッチする。
3)ポインターでキャッチ。
値によるキャッチはオブジェクトの2つのコピーを呼び出し、参照によるキャッチは1つを呼び出すことだけを知っています。では、ポインタによるキャッチはどうでしょうか?ポインタによるキャッチはいつ使用するのですか?オブジェクトをスローするだけでなく、このようなオブジェクトへのポインターをスローできますか?
class A {}
void f() {
A *p = new A();
throw p;
}
推奨される方法は、値でスローし、参照でキャッチすることです。
サンプルコードはポインターをスローしますが、catchサイトでメモリを管理する必要があるため、これは悪い考えです。
ポインタをスローする必要があると本当に感じた場合は、shared_ptr
などのスマートポインタを使用してください。
とにかく、ハーブサッターとアレクセイアレクサンドレスクは、私が言い換えたC++コーディング標準の本でそれを非常によく説明しています
C++コーディング標準:値によるスロー、参照によるキャッチ を参照してください。
キャッチは、通常の割り当て互換性規則に従います。つまり、値をスローした場合、値または参照としてキャッチできますが、ポインターとしてはキャッチできません。ポインターをスローした場合、それはポインター(またはポインターへの参照...)としてのみキャッチできます。
しかし、ポインタをスローすることは実際には意味がなく、メモリ管理の頭痛を引き起こすだけです。したがって、Gregoryで説明されているように、一般にルール値によるスロー、参照によるキャッチに従う必要があります。
MicrosoftのMFCはポインタによるキャッチを使用しますが、これは、try and catchが適切に実装される前のコンパイラとの互換性のためだと思います。もともと彼らはそれをシミュレートするためにTRYとCATCHマクロを使用していました。各例外はCExceptionから派生します。CExceptionには、オブジェクトを削除する必要があるかどうかを判別するメソッドがあります。
現代の例外設計では、これをお勧めしません。参照によるキャッチは、進むべき道です。
本質的に任意のタイプの任意のオブジェクトをスローすることは可能ですが、これを行うことで得られることは(もしあれば)ほとんどありません。動的割り当ては、主に、オブジェクトの存続期間を自動割り当てに適合させる必要がない場合に役立ちます。つまり、その存続期間を通常のプログラムスコープから独立させたい場合です。
ただし、例外オブジェクトの場合は、あまり意味がありません。例外オブジェクトは通常、例外ハンドラーの内部でのみ使用され、その例外の(最後の)ハンドラーを終了するときに、それを破棄したいことは明らかです。
また、例外処理コードをかなり単純にしておく必要があるという事実もあります。たとえば、空きストア/ヒープが枯渇または破損していることを報告しようとしている場合、その枯渇/破損した無料ストア/ヒープから例外オブジェクトを割り当てようとしても、通常はうまく機能しません...
ポインタによる例外をキャッチ/スローするための良いシナリオは実際にはありません。 C++のセマンティクスはそれを許可しますが、ほとんどの場合、一時的な例外または文字列オブジェクトをスローするため、それほど有用ではありません。
ただし、一部のライブラリー(Boost.Graphはこれを行うと思います)は、throwを使用して、深く再帰された関数から呼び出し元に戻り値を返します。このような状況では、戻り値がポインターになる可能性があるため、ポインターをスローすることは理にかなっています。