2016-11-04 4 views
1

をどのように機能するかをオペレータに新しい、私は単純なコードを持っている:C++、これは例えば、内部

class B 
{ 
}; 

class A 
{ 
    B b; 
    public: 
    A() 
    { 
     throw 1; 
    } 
}; 

int main() 
{ 
    A* a = 0; 
    try 
    { 
     a = new A; 
    } 
    catch (int) 
    { 
    } 
} 

コンストラクタAは、デストラクタが呼び出されることはありません、例外がスローされます。しかし、Bのデストラクタが呼び出されます。ヒープ内のメモリは割り当てられません。私の質問は内部的にどのように動作するのですか?最初になるもの:Aを構築するか、ヒープにメモリを割り当てるか?したがって、割り当てが最初の場合、例外がある場合、どのように割り当て解除が処理されますか?その他、Aを構築するのが最初の場合、ヒープにどのようにコピペしますか?

答えて

4
  1. メモリが割り当てられます。
  2. Aのコンストラクタが呼び出されます。
  3. AのコンストラクタはBのコンストラクタを呼び出します。
  4. Aのコンストラクタがスローします。
  5. 標準例外処理プロシージャの一部として、Bのデストラクタが呼び出されます(RAIIの作業時)。
  6. スタックは呼び出し側(メイン)に巻き戻されます。
  7. メモリが割り当て解除されました(オブジェクトが正常に構築されなかったため)。

オブジェクトが完全に構築されていないため、Aのデストラクタが呼び出されません。しかしながら、であったメンバーは完全に構築されたである。

メモリは、コントロールがブロックを離れるときにローカル変数が破壊されるのとほぼ同じ方法で自動的に割り当てが解除されます。あなたがJavaやC#に慣れているなら、それを目に見えないtry-finally構造と考えてください。または一連のそのような構造物。

+0

ありがとうございます、あなたのコメントはいいですが、私はより多くの情報が必要です。スタックのようなヒープメモリ内のデストラクタの動作を提供するメカニズムは何ですか? – M90

+0

@ M90、私はメカニズムが実装固有のものだと思います。私が言ったように、目に見えない 'try-finally'ブロック。同様に、何かがうまくいかない場合、コントロールは必要な処理が必要なものを処理する自動生成コードに転送され、次に伝播の例外が続きます。あなたが興味をそそられていれば、あなたのコードをアセンブリにコンパイルして*本当に*動作するかどうかを確認してください。 –

+1

@ M90も参照してください。Herb Sutterの[Constructor Failures ...](http://www.gotw.ca/publications/mill13。htm) –

0

最初になるもの:Aを構築するか、ヒープにメモリを割り当てますか?

メモリがない限り、オブジェクトを構築するためのスペースはありません。メモリの割り当ては常に優先されます。コードは初期化を続行します。これは、オブジェクトの初期化を開始する前に、コンストラクタがthisという有効なアドレスを持つ必要があるため、ダイナミックバラエティだけでなく、あらゆる種類のメモリ割り当てに適用されます。

割り当てが最初の場合、例外が発生した場合、どのように割り当て解除が処理されますか?

コンパイラは、ここで「魔法」を扱う特別なコードを発行します。このコードでは、すべての基本クラス、およびAのコンストラクタを入力した時点で完全に構築されたメンバー(Bなど)のデストラクタが実行されます。

+0

ありがとう、この「特別なコード」の動作を詳細に記述してください。 – M90

+0

@ M90私はすでに行っています:完全に構築されたすべてのデストラクタを実行し、割り当てられたメモリを元の場所に戻します(あなたの場合はヒープから来て、ヒープに戻ります)。 – dasblinkenlight