コンストラクタ中での例外

nil
記事: 428
登録日時: 14年前

コンストラクタ中での例外

投稿記事 by nil » 13年前

クラスのコンストラクタ内で例外が投げられ、そのコンストラクタ内でcatchされなかった場合、デストラクタは呼び出されない
► スポイラーを表示

コンストラクタ内で例外を投げそうな処理を呼び出すときはtry文で囲んでデストラクタで行う処理を呼び出してからまた投げる……
一層程度ならまだいいでしょうがクラスの関係が複雑化すると、クラスにオブジェクトを追加した時にうっかり忘れて……なんてミスが発生しそうですね
► スポイラーを表示
さて、どうするのが一番いい手なのでしょう?
コンストラクタの役割を奪ってInit関数を追加する、ですかね?
みなさんはどう思いますか?

ISLe
記事: 2650
登録日時: 15年前

Re: コンストラクタ中での例外

投稿記事 by ISLe » 13年前

デストラクタが呼び出されないのではなくて、例外によってnew演算子の戻り値が代入されないので、ヌルのままのbをdeleteするので何も起きないわけです。

こういうときのためにスマートポインタがあるのですよ。
この場合はstd::auto_ptrが軽くてお勧めです。

nil
記事: 428
登録日時: 14年前

Re: コンストラクタ中での例外

投稿記事 by nil » 13年前

なるほど……アドレスを受け取る事ができないのでdeleteができない、ということですか……

スマートポインタですか……盲点でした。
ちょうどboostの1.50.0が出たので試してみようと思います
auto_ptrってboostには入ってないんですね。tr1の方でした
最後に編集したユーザー nil on 2012年7月06日(金) 22:15 [ 編集 1 回目 ]

アバター
tk-xleader
記事: 158
登録日時: 14年前

Re: コンストラクタ中での例外

投稿記事 by tk-xleader » 13年前

コンストラクタの内部で例外が投げられ、それが内部で処理されなかった場合、オブジェクトが完全に初期化されたわけではありませんから、不完全な状態になってしまい、デストラクタが投げられることがありません。ただし、メンバ変数のデストラクタは呼ばれます。それらは、一応オブジェクトとして生成が終了してますからね。
この場合、スマポにするべきなのは、クラス内部のメンバです。要するに、クラスの内部でナマポを直接使うのではなく、shared_ptr や unique_ptrを使うことによって、オブジェクト単位でリソースを管理するようにしたほうがいいです。ちなみに、unique_ptrは、デリータをパラメータによって指定できますから、newによって生成されたオブジェクト以外のリソースも管理可能です。

nil
記事: 428
登録日時: 14年前

Re: コンストラクタ中での例外

投稿記事 by nil » 13年前

tkmakwins15 さんが書きました: この場合、スマポにするべきなのは、クラス内部のメンバです。
コメントありがとうございます。

つまり、Bのコンストラクタ内で例外が投げられる可能性がある場合、

CODE:

class B{
	std::unique_ptr a;
public: B(){ a = std::unique_ptr(new A); }
};
としてやることでメモリリークを防げるわけですね