2

コンストラクターを持つクラスがあるとしましょう:

class MyClass
{
public:
    MyClass()
    {
    //our code goes here
    throw "OMG";//well, some code that throws an exception
    }
};

現在、例外が発生すると、スタックの巻き戻しが実行されます。また、コンストラクタから例外がスローされた場合、オブジェクトが最初から完全に「作成」されたことがないため、対応するオブジェクトのデストラクタが呼び出されないことも知っています。

私はこれに少し混乱しています。私にとって、これは、コンストラクターが終了したときにのみオブジェクトが「作成された」と見なされることを意味します。ただし、コンストラクター内でオブジェクトのメンバーを操作できるため、コンストラクターが呼び出される前(または直後)のどこかにすべてのメモリーが割り当てられることは明らかです。

では、オブジェクトがメモリ内に作成されるのはいつですか。また、例外の原因となったオブジェクトのメモリはどうなりますか?

4

3 に答える 3

2

C ++では、メモリ割り当てオブジェクト構築は2つの別個のものです。コンパイラーは、thayが一緒に呼び出され(通常の-つまり、非配置-new演算子の場合)、構築が失敗したときに、割り当てが元に戻されることを確認します。

また、クラスにサブオブジェクト(基本クラスやフィールド)がある場合、コンパイラはコンストラクタを一定の順序で呼び出し、そのうちの1つがスローされた場合よりも、すでに構築されたサブオブジェクトが適切に破棄されるようにします(つまり、 、デストラクタを呼び出します)。

于 2012-08-23T08:22:55.593 に答える
2

メモリは、コンストラクターの本体の前に割り当てられます。

コンストラクターが失敗した場合、自動的に割り当てられたメモリーが解放されます。

また、「自動的に割り当てられる」というアクセントが重要です。コンストラクターに動的にメモリを割り当てていて、コンストラクターが失敗した場合(たとえば、new以前に使用したことがある場合throw "OMG")、このメモリはリークします。

これは、このメモリを割り当てたので、それを解放する必要があるためです。

確かに、デストラクタは呼び出されませんが、クラスの自動メンバーに割り当てられたメモリを解放するデストラクタではありません。
これは(基本的に)メモリを解放するために使用され、ユーザーによって(コンストラクターまたは他の場所で)割り当てられます。


つまり、オブジェクトにメモリを割り当てることは、オブジェクトの構造とは異なります。

別の例-次のようにオブジェクトを動的に作成する場合:

MyObj* = new MyObj;

この意志:

  • 電話operator new
  • 次に、のコンストラクタを呼び出しますMyObj

ほら、両方とも違う。

于 2012-08-23T08:23:32.177 に答える
1

オブジェクトのメモリは解放されますが、デストラクタは呼び出されません(したがって、コンストラクタで例外を正しく処理しないと、コンストラクタ内で作成された動的に割り当てられたポインタは解放されません)。C ++ 11の仕様では、 1つのコンストラクターが完全に完了した場合にのみ、デストラクタが呼び出されると規定されています(コンストラクターは別のコンストラクターを参照できるため、関連性があります)。

例(new int()によって割り当てられたメモリは解放されません):

struct Broken {
   int * i;
   Broken () {
      i = new int {5};
      OperationCausingException ();
   }

   ~Broken {
      delete i;
   }
}

try {
   Broken * b = new Broken {};
} catch (...) {
}
// memory leak: *b is freed, but b->i still exists
于 2012-08-23T08:21:22.507 に答える