代わりに std::unique_ptr (あるいは boost::scoped_ptr )を使います.
何故か?
struct hoge { hoge() : xxx( get_resource() ) { /* 処理 */ if( some_cond ) throw some_exception(); /* さらに処理 */ } ~hoge() throw(){ release_resource(xxx); } /* ... */ private: XXX xxx; };
このようなコードで,コンストラクタ中に例外が投げられた場合,
デストラクタが呼ばれず,解放漏れが起きるからです.
このような露骨な場合でなくても,
struct hoge { hoge() : xxx( get_resource() ), yyy() // ここで例外! { } ~hoge() throw(){ release_resource(xxx); } /* ... */ private: XXX xxx; YYY yyy; };
とか,普通にありえる状況ではないでしょうか.
一般に,コンストラクタ中で例外が投げられた場合,そのクラスのデストラクタは呼ばれません.
しかし,そのような場合でも,既に初期化されたメンバのデストラクタは呼ばれます.
故に,デストラクタを使うクラスは,可能な限り,小さなクラスにするべきで,
その「可能な限り小さなクラス」の代表例が, std::unique_ptr なのです.
// リソース開放用ファンクタ struct XXX_releaser { typedef XXX pointer; void operator( XXX xxx ){ release_resource(xxx); } }; // unique_ptr に typedef する typedef std::unique_ptr<XXX, XXX_releaser> XXX_pointer; // リソース取得関数は unique_ptr を返すようにすると良い // 今回はラッパなので微妙だが inline XXX_pointer get_xxx() { return XXX_pointer( get_resource() ); } // 本体 struct hoge { hoge() : xxx( get_xxx() ), yyy() { } // デストラクタは書かない /* ... */ private: XXX_pointer xxx; YYY yyy; };
実際,殆どの場合で,デストラクタは std::unique_ptr に置き換え可能です.
故に繰り返します. 本物のC++erはデストラクタをイチイチ書きません.
これからは std::unique_ptr を使いましょう.