関数内のオブジェクトの解放手法のまとめ

前提

  • 関数内でのエラーはすぐにチェックしてreturn(goto)する。成功時のみのif文の書き方はしない
    • ネストを浅くするため。欠点として、オブジェクトの解放場所を考慮する必要が出てくる。
    • ケント・ベックの"実装パターン"の"ガード条件"で記述されている。

言語

C
  • gotoで解放
    • ポインタをNULLで初期化して、エラー時にはgotoでerr_exitに抜けて、err_exit:でNULLでない場合に解放する
      • ANSI Cではfree()(deleteも同じ)はNULLの場合に何もしないので、err_exit:でのNULLチェックは不要。
        • free()をwrapしてNULLが来たときにはエラーにするプロジェクトもあるが、意図の明確化(このコードでNULLがあり得ることの表明)の利点より、コードの複雑生の向上の欠点の方が大きい気がする。
C++
  • デストラクタで解放
    • newでない場合(初期化ですむ場合)のみ可能
  • auto_ptr
  • スマートポインタ(boost)
  • __finally(非標準)
Java
  • GC
    • javaのファイナライザはいつ呼ばれるか不明なので、メモリなどの解放以外は不適
  • finally
C#
  • GC
    • javaと同じで、デストラクタのタイミングが不明なので、メモリなどの解放以外は不適
  • finally
  • using&dispose

状況

  • オブジェクトを確保しないが、失敗時のキャンセルが必要な処理の場合
    • a_okなどの変数をfalseで初期化し、処理の成功時にtrueを格納し、後はC言語の"gotoで解放"等と同じ
    • 複数のgotoの移動先を使う方法もあるが、順序を変えただけでバグになるので、使わない。
  • for文の中でオブジェクトの確保をした場合
    • C言語のgotoが使えないので、繰り返し部分を別関数にする。