2012-06-08 10 views
86

私が上につまずいたいくつかのコードを見ながら:スロースローSTD対新しいのstd ::例外::例外

throw /*-->*/new std::exception ("//... 

と私はいつもあなたが/あなたがここにnewを使用してはならない必要はありませんと思いました。
正しい方法は何ですか、両方ともOKですか、違いがあれば?

私はPowerShellのブーストライブラリで "grepping"が表示されているものは、throw newを使用しないでください。

P.S.また、throw gcnewを使用するCLIコードがいくつか見つかりました。それは大丈夫ですか?

+0

私は 'gcnewをスローすると便利だと思います。例外をキャッチするマネージコードが必要な場合誰かがそれを修正できますか? – jpalecek

+1

.Netはポインタで例外を処理するので、gcnewをスローすることが適切です。 –

+1

@SebastianRedl .Net "ポインタ"はあいまいかもしれませんか?確かにgcnewはそうではありません。 'System :: Exception'は一般的に、ガベージコレクトされたヒープ上の管理オブジェクトへの参照です。私はいつも 'gcnew'を投げて' System :: Exception^'と捕まえました。もちろん、私はいつもC++/CLIで 'finally 'を使用していますが、同じ' try'ブロックでC++例外と混同されることはよくありません。理由はわかりません。 –

答えて

72

例外をスローしてキャッチする従来の方法は、例外オブジェクトをスローし、参照(通常はconst参照)でキャッチすることです。 C++言語では、例外オブジェクトを構築し、適切なタイミングで適切にクリーンアップするための適切なコードをコンパイラが生成する必要があります。

動的に割り当てられたオブジェクトへのポインタを投げることは決して良い考えではありません。例外は、エラー状態に直面してより堅牢なコードを書くことができるようになっています。通常の方法で例外オブジェクトをスローした場合は、正しい型を指定するcatch節でキャッチされたかどうかを、catch (...)で確認して、再投げられるかどうかを適切な時期に正しく破棄するかどうかを確認できます。 (唯一の例外は、まったくキャッチされない場合ですが、これは復旧できない状況です。)

動的に割り当てられたオブジェクトへのポインタを投げる場合は、コールスタックは例外をスローしたい点のように見えます。キャッチブロックには正しいポインタタイプが指定され、適切なdeleteコールがあります。そのブロックが例外を再スローしない限り、その例外を正しく処理する別のキャッチブロックがキャッチされない限り、例外はcatch (...)によって捕らえられてはなりません。

効果的には、例外処理機能を使用することで、堅牢なコードを簡単に作成できるようになり、すべての状況で正しいコードを作成するのが非常に困難になります。これは、この機能を期待していないクライアントコードのライブラリコードとして機能することがほとんど不可能になるという問題を除いています。

+1

「例外オブジェクトをスローする」スタックをリンクしたり、友人をヒープしたりしましたか?スタックまたはヒープ? (たぶん私はどこかで悪いグローバルな例を見ていた)ああ、スタックの場合は、適切な範囲は何ですか? –

+0

@ebyrob:あなたが尋ねていることは本当にわかりませんが、答えられる可能性のある例外オブジェクトの記憶域や寿命について知りたいと思うように思えます(http://stackoverflow.com)。/questions/1654150/scope-of-exception-object-in-c)を参照してください。そうでない場合は、別の質問をする方が良いかもしれません。 –

26

例外をスローするときにはnewを使用する必要はありません。

だけ書く:

として
throw yourexception(yourmessage); 

とキャッチ:yourexceptionが直接または間接的にstd::exceptionから派生する必要があることを

catch(yourexception const & e) 
{ 
     //your code (probably logging related code) 
} 

注意を。

+5

なぜですか?なぜ 'new'を使わないのですか? 'std :: exception'から' yourexception'を引き出すのはなぜですか? – Walter

+0

私は怠け者です(これはたいていの場合waaayです)なぜ 'throw std :: exception;'は動作しませんか? g ++はそれをコンパイルしていないようです... –

+5

@ebyrob: 'std :: exception'は型です。*型*を投げることはできません。*オブジェクト*をスローする必要があります。したがって、構文は次のようになります: 'throw std :: exception();'これはコンパイルされます。今、どれだけいいですか、全く別の質問です。 – Nawaz

21

コールサイトがstd::exception*をキャッチする予定の場合、new std::exceptionを投げることは正しいです。しかし、誰も例外へのポインタをキャッチすることを期待することはありません。あなたの関数が何をしているのかを文書化し、人々がドキュメントを読んでも、彼らはまだ忘れて、代わりにstd::exceptionオブジェクトへの参照をキャッチしようとします。

+25

'new std :: exception'を投げることは、コールサイトがポインタをキャッチしようとしていて、割り付け例外の管理を引き継ぐことを期待していて、関数が呼び出されることは決してありません明示的に正しいポインタ( 'catch(...)'や全く処理しない)がある場合は、オブジェクトリークが発生します。要するに、これは「決して」と近似することができます。 –

+0

この答えがどのように受け入れられたのか不思議です。本当にCharlesBaileyの* comment *が正しい答えです。 –

+0

@ジョン:それも私の心を越えた。しかし、1/2のパンチは、ドライ・サマリーとチャールズに人々がそれを適切に処理することを忘れる可能性がある様々な方法を面白く拡大して、私に良い影響を与えると思う。あなたが投票したコメントから評判を得られないのは残念です。 – Hurkyl

7

C++ FAQは、この上の素敵な議論があります。

  1. https://isocpp.org/wiki/faq/exceptions#what-to-catch
  2. https://isocpp.org/wiki/faq/exceptions#catch-by-ptr-in-mfc

基本的には「正当な理由は、参照によってキャッチ値でキャッチ避けるためにではないがありますしない限り、コピーが作成され、コピーはスローされたものとは異なる振る舞いをすることがあります。非常に特殊な状況下でのみ、ポインタを捕まえるべきです。

+2

いつものように、FAQはひどく言われています。あなたは価値観や参考資料で捉えることができます。ポインタはちょうど値(値または参照によってキャッチ)であることがあります。 'A'型は' A * '型とは別の型であることを忘れないでください。そうすれば、私は' catch(A * e) 'と全く違うタイプなので' A() 'をキャッチできません。 –

+0

これらのリンクは現在破損しています。 – spanndemic

+1

@spanndemic – user1202136

関連する問題