2

コード :

#include<iostream>
using namespace std;
class A{
    public:
    A(){cout << "A() Constructor " << endl;
        throw 1;
    }

};


int main(){
A* p=0;
cout << p << endl; // p value is 0
try{
p=new A(); // object is not fully constructed, no address is returned to p. for future deallocation

}
catch(...){cout << "Exception" << endl;}
cout << p << endl; // this will output that p has the value 0,proof that no address was returned to p.


}

メモリがヒープ内のオブジェクトに割り当てられ、メモリのアドレスがコンストラクターに渡されますが、コンストラクターの場合throw 1;、型のオブジェクトはA完全に構築されたオブジェクトとは見なされません。したがって、ポインター p にはポインターは返されません。何か間違ったことを理解した場合は、遠慮なく修正してください。

質問:
1)したがって、私の質問は、そのような場合に A オブジェクトのメモリの割り当てを解除する方法です。私はデストラクタ呼び出しについて話しているのではなく、メモリの割り当て解除について話しています。

2)A関数内の型のローカル オブジェクトを作成するとどうなりますかmain。明らかに、完全に構築されることもありません。このオブジェクトはいつ割り当て解除されますか (もちろん、完全に構築されたサブオブジェクトのデストラクタを呼び出した後)。

4

4 に答える 4

5

1) 割り当て解除が行われます。

2) ローカル オブジェクトの場合、最初から割り当てられていません。

于 2012-10-21T20:44:01.490 に答える
5

コンストラクターがそのオブジェクトに割り当てられたメモリをスローすると、自動的に解放されますが、デストラクタは呼び出されません。割り当てを解除する必要はありません。

于 2012-10-21T20:46:06.907 に答える
4

によって行われる割り当てnew A()は、複数のステップで構成されます。

  1. を使用してメモリを割り当てますoperator new(sizeof(A))
  2. 割り当てられたメモリでオブジェクトをデフォルトで構築してみてください。
  3. デフォルトの構築に失敗operator delete(x)すると、先に取得したアドレスで呼び出されます。

より一般的には、オーバーロードされた を使用する場合operator new()、たとえばnew(allocator) A()which を呼び出すoperator new(size_t, Alloctor)( whereallocatorは に変換可能Allocator) と、対応するoperator delete()が呼び出されます。

例外スローの一部として、部分的に構築されたすべてのサブオブジェクトも (構築された順序とは逆の順序で) 破棄されます。つまり、オブジェクトのコンストラクターから例外がスローされた場合、クリーンアップを気にする必要はありません (すべてのサブオブジェクトが、割り当てられたリソースを正しく処理していると仮定します)。これは、オブジェクトがヒープまたはスタックに割り当てられているかどうかに関係なく当てはまります。

于 2012-10-21T20:49:38.473 に答える
1

CPP では、コンストラクター (ctor) 呼び出しのシーケンスは次のとおりです。

  • 仮想基底クラス:深さ優先シーケンスに従って呼び出す仮想基底 ctor。
  • 基本クラス: クラスを定義する際の派生宣言に従った基本クラスの呼び出しシーケンス。
  • 非静的メンバー オブジェクト
  • 派生クラス ctor;

デストラクタ (dtor) は逆の順序で呼び出されます。

CPP は、完全に構築されたオブジェクト (ポインターではない) のリソースが確実に解放されるようにします。

RAII (Resource Acquisition Is Initialization) があります。オブジェクトを使用して生のポインターをラップしてメモリを割り当て、dtor でメモリを解放します。派生オブジェクトが (メモリ不足、例外など) のために部分的に構築された場合、メンバー オブジェクト dtor が呼び出されます。

上記の単純な例では、リソースが割り当てられていないため、リソース リークはありません。

ただし、throw の前にメモリを割り当てるメンバ ポインタがあると、メモリ リークが発生します。メモリをクラスにラップし、このクラスのオブジェクトを (RAII を使用して) コンポーネントとして作成すると、メモリ リークは発生しません。

于 2014-06-04T12:32:05.133 に答える