2011-12-03 9 views
1

私はクラスAを持っていて、そのコンストラクタにはnewを使ってメモリを割り当てています。 Aのチャンクを割り当てて(が1つのAを初期化している間に)1つがstd::bad_allocをコンストラクタにスローするとどうなりますか?演算子newは例外の後に初期化されたオブジェクトを破棄しますか?

operator new[]はすでに初期化されたオブジェクトを破棄しますか? コンストラクタがスローしないようにするのは私の義務ですか?

EDIT:新しいの2つの呼び出しが混乱に聞こえるかもしれないので、ここで明確にするコードの一部です:

class A 
{ 
    int* mem; 
public: 
    A() 
    { 
     try 
     { 
      mem = new int[3]; 
     } 
     catch(bad_alloc&) 
     { 
      throw 5; 
     } 
    } 
    ~A() 
    { 
     delete[] mem; 
    } 
} 

A* list = 0; 

try 
{ 
    list = new A[50000]; 
} 
catch(int) 
{ 
    // When I get here, did the new[] above call the destructors 
    // of all the objects it managed to construct before one of them threw? 
} 

答えて

3

new Foo()を実行し、Fooのコンストラクタがスローすると、関連するoperator newによって割り当てられたメモリが解放されます。 Fooのメンバーのコンストラクターが成功した場合、そのメンバーのデストラクタが呼び出されます。

new Foo[100]を実行して42番目のコンストラクタがスローすると、既に構築されたすべてのFooオブジェクトが(逆の順序で)破棄されます。

+0

私はいくつかのコードを追加しました。 – pezcode

+0

はい、ありがとうございます。短い答えは「はい」ですが、私の答えを編集しました。 –

0

メンバーは破棄されます。コンストラクタ内の自動継続時間変数は範囲外になり、適切に破棄されます。

+0

を、あなたは普通の言葉でそれを説明することはできますか?私は完全に理解しているか分からない。ありがとう:) – pezcode

+0

@pezcode:「あなたは大丈夫です」はとてもシンプルです。 –

0

いくつかのフィールドがコンストラクタで正常に初期化されている場合、デストラクタは自動的に呼び出されます。

1

はい、すでに割り当てられているオブジェクトはすべて削除されます。なぜ自分でそれを試してみませんか?

#include <iostream> 
#include <stdexcept> 

class A { 
    static int n; 
public: 
    A() 
    { 
     ++n; 
     std::cout << "construncting A no. " << n << "..."; 
     // let's pretend we allocate something here 
     // with new and it fails 
     if (n == 5) { 
      std::cout << std::endl; 
      throw std::bad_alloc(); 
     } 
     std::cout << "done\n"; 
    } 
    ~A() 
    { 
     --n; 
     std::cout << "destructed A no. " << n << "\n"; 
    } 
}; 

int A::n = 0; 

int main() 
{ 
    try { 
     A* a = new A[10]; 
    } 
    catch (std::bad_alloc& e) { 
     std::cout << "caught an exception!\n"; 
    } 
} 

ただし、コンストラクタが投げたインスタンスのデストラクタは呼び出されません(上記のコードを実行すると分かります)。それでも、その時点で構築されたメンバーは削除されます。たとえば、このコンストラクタがスローした場合、:

class foo { 
    int i; 
    bar* b; 
public: 
    foo() : i(42), b(new bar) 
    { 
     float f = 3.14; 
     // something throws an exception here 
    } 
    ~foo() 
    { 
     delete b; 
    } 
}; 

ibfが削除されます、しかし、割り当てられたメモリが解放されません(delete bが呼び出されません)、あなたは(メモリリークを持っていますスマートポインタを使用すると簡単に解決できます)。

これについての詳細はC++ FaqLiteを見てみましょう:

http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.10

http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.8

関連する問題