オブジェクトを構築するときに例外が発生した場合、いくつかの興味深い動作を見つけました。
class bookentry
{
public:
bookentry(){
t1.reset(new test1); //0
test1 *t11 = new test1; //1
test2 *t22 = new test2; //2
throw 1; //3
}
protected:
private:
auto_ptr<test1> t1;
auto_ptr<test2> t2;
};
私がテストしたものから:
test2 のコンストラクター (#2)から例外をスローすると、
- t1 : 完全に破棄されます。つまり、t1 のデストラクタが呼び出され、メモリが解放されます。
- t11 : 破棄されることはありません (t11 のデストラクタを呼び出したり、メモリを解放したりしません)。
- t22 : これは面白い部分です。t22 のデストラクタは呼び出されませんが、t22 のメモリは解放されます!
bookentry のコンストラクター (#3)から例外をスローすると、今回は少し異なります: t22は決して破棄されません (t22 のデストラクタを呼び出すことも、メモリを解放することもありません)。t11 は上記と同じです。
#2の文と混同しています
test2 *t22 = 新しい test2; //2
クラスコンストラクターから例外をスローすると、 new 式は対応する削除が呼び出されることを確認しますが、その例外の前に new 式を介して完全に作成されたオブジェクトはリークされます (t11、または t11 および t22 をスローした場合) #3の例外)。
したがって、以下のようなコードを書き、5 番目のオブジェクトの構築に失敗した場合:
test2 *t2s = 新しい test2[10];
次に、少し安全なようです:
- すでに構築されたオブジェクトは破棄されます。
- メモリが解放されます。
私の質問は、これは標準的な C++ の動作ですか? msvc 2012 と gcc 4.4.6 をテストしたところ、どちらもそのようなメカニズムを実装しているように見えます。
私の質問をより明確にするために編集してください:
場合によっては、他の通常の関数で t1.reset(new test1) [コードの #1 を参照] のようなコードを記述する必要があります。そのような場合、コンストラクターから例外がスローされた場合。プログラムの状態を判断するにはどうすればよいですか? メモリリークはありますか?
私のテストでは、これらがそのような場合にメモリリークがないことを確認していますが、それは標準的な C++ の動作ですか?