2012-10-04 5 views
6

可能性の重複:私は6つのオブジェクトを作成していた場合、私はコンストラクタで例外を処理し、それらのオブジェクトは5オブジェクトを作成し、第六1を作成中に失敗するにはどうすればよい
How to clean initialized resources if exception thrown from constructor in c++コンストラクタで例外を適切に処理するにはどうすればよいですか?

ありがとうございました。

+3

リンクは、Alsがあなたにここで提供するリンクはどうですかhttp://stackoverflow.com/questions/12723492/how-to-clean-initialized-resources-if-exception-thrown-from-constructor-in-c?このメンバはメンバオブジェクトですか? – ForEveR

+0

どのような取り扱いが必要ですか?通常、例外を伝播させるだけで、最初の5つのオブジェクトは完全に破棄されます。いくつかの文脈が役に立つでしょう – jalf

+0

RAII。(http://ja.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization) – ScaryAardvark

答えて

1

コンストラクタで例外がスローされると、完全に構築されたすべてのサブオブジェクトが破棄されます。構築されたオブジェクトのデストラクタをresoyrcesに見せてもらうのがよい習慣であるので、これらのサブオブジェクトに対して何もする必要はありません。まだ残っているのは、例外がスローされたときに現在実行中のコンストラクタの本体でクリーンアップすることです。ただし、これは他の機能のクリーンアップと同じです。

破壊順序は構造の逆です。つまり、ボディ内のクリーンアップは、すべてのサブオブジェクトがまだ破壊されていないときにはじめて開始されます。その後、メンバーは破壊され、次に非仮想基本クラス、そして最後に仮想基本クラスが破棄されます。

3

通常の動作では、例外を伝播させるだけです。デストラクタ 完全に構築された基本クラスとメンバが呼び出されます。 最初の5つのオブジェクトがメンバーの場合、それらは正しく 破壊されます。

問題が発生する可能性があるのは、 というオブジェクトが動的に割り当てられている(newを使用している)場合のみです。それが の場合:最初に自分に尋ねるのはなぜですか?なぜあなたは動的にオブジェクトを割り当てていないのですか? は具体的なメンバーですか? 私の経験では、このような必要性は非常に稀ですが、いくつかの特別な場合を除いて、 ケース(コンパイルファイアウォールのイディオムなど)の場合は、通常、クラス内のオブジェクトはちょうど です。 実装オブジェクト)。そのような場合、そのオブジェクトの newに障害が発生した場合、何も行われていないので、何も問題はありません。 を元に戻す必要があります。

あなたが本当に 動的割り当てを使用しなければならないのどこに非常にまれなケースで自分自身を見つける場合は持っている以上のようなオブジェクト (例えば、あなたは、多型二つのサブオブジェクトを持っているので)、その後、 あなたを割り当てのそれぞれがサブオブジェクトの一部の ソートにラップされていることを確認する必要があります(スマートポインタがトリックを行います)。最初の サブオブジェクトが正常に構築されると、後でそのコンストラクターが失敗すると、そのデストラクタが呼び出されて になります。

1

例外を処理する "コア"は、事実上すべてがデストラクタを介してクリーンアップされるべきであるということです。たとえば、オブジェクトを「新規」にすると、「生の」ポインタが得られます。例外がスローされた場合は、この生ポインタが適切に "削除"されていることを確認する必要がありますが、初期化されていない生ポインタは削除しないでください。

一方、そのポインタをstd :: unique_ptrに格納すると、何もする必要はありません。 unique_ptrが破棄されると、オブジェクトは削除され、オブジェクトの破棄が自動的に発生します:unique_ptrが有効範囲外になると、コンパイラーは完全に見えなくなります(コードが煩雑になることはありません)もう誰も本当にクリーンアップするのを忘れてしまったという珍しい道を辿ると、それはもはや「ああ」ではない)。

ほぼすべてのリソースに同じことを適用できます。 COMオブジェクトのための "自動ポインタ"(DirectXで使われているような)がありますが、ほとんどのフレームワークはmutexをラップするために "スコープロック"タイプのオブジェクトを与えるべきです(オブジェクトが作成されるとmutexをロックします。破壊されたときにロックを解除する)、さまざまなWindowsハンドルに対処するための小さなラッパーを作成することができます。

基本的に、すべてのクリーンアップをデストラクタに入れると、クリーンアップするだけで "キャッチ...再登場しようとする必要はありません"。事実上すべての "包含"されたオブジェクトはデストラクタによって自動的にクリーンアップされるので、 "大きな"オブジェクトのデストラクタはしばしば非常に簡単です。

関連する問題