は削除のポインタをサブクラスの基底クラスデストラクタ?
-
21-08-2019 - |
質問
私は class A
を使用するヒープメモリ割り当てのための一つ。ラスのインスタンスが作成して保存したポインタの分野別のクラスclass B
.
私は、オブジェクトのクラスB、私 delete
, るいはデストラクタ...ではこの呼び出しのデストラクタのクラスでも見ることができますか?
編集:
からの回答をしていること(編集が間違った):
delete
のインスタンスのマー B::~B();- を呼びかけ
A::~A();
A::~A
すべ 明示的にdelete
すべてのヒープの割り当てのメンバ変数は、オブジェクト- 最後に、メモリブロックの保管とのインスタンスBクラスが返されるエディタで開き、ヒープが 新しい 使用したので、最初に割り当てるメモリブロックヒープを呼び出しのコンストラクタを初期化する方法についても、今後すべてのdestructors呼び出されたものを完了させるためのオブジェクトのブロックのオブジェクトに滞在が返されるヒープ.
解決
その寿命が終わったとき、Aのデストラクタが実行されます。あなたはそのメモリが解放され、デストラクタの実行させたい場合は、それがヒープに割り当てられた場合、それを削除する必要があります。それはスタック上に割り当てられた場合(これはスコープの外に出たとき、すなわち、RAIIを参照)、これは自動的に行われます。それはクラスのメンバ(ないポインタが、完全なメンバー)である場合を含むオブジェクトが破棄されるとき、これは起こる。
class A
{
char *someHeapMemory;
public:
A() : someHeapMemory(new char[1000]) {}
~A() { delete[] someHeapMemory; }
};
class B
{
A* APtr;
public:
B() : APtr(new A()) {}
~B() { delete APtr; }
};
class C
{
A Amember;
public:
C() : Amember() {}
~C() {} // A is freed / destructed automatically.
};
int main()
{
B* BPtr = new B();
delete BPtr; // Calls ~B() which calls ~A()
C *CPtr = new C();
delete CPtr;
B b;
C c;
} // b and c are freed/destructed automatically
上記の例では、すべての[]は必要とされているを削除し、削除します。そして、何の削除は(実際に使用することができたり)私はそれを使用していないところ必要ありません。
auto_ptr
、unique_ptr
とshared_ptr
等...この寿命管理がはるかに簡単に作るための素晴らしいです。
class A
{
shared_array<char> someHeapMemory;
public:
A() : someHeapMemory(new char[1000]) {}
~A() { } // someHeapMemory is delete[]d automatically
};
class B
{
shared_ptr<A> APtr;
public:
B() : APtr(new A()) {}
~B() { } // APtr is deleted automatically
};
int main()
{
shared_ptr<B> BPtr = new B();
} // BPtr is deleted automatically
他のヒント
あなたは新しいによって割り当てられたポインタに削除を呼び出すと、オブジェクトのデストラクタが呼び出されますし指さます。
A * p = new A;
delete p; // A:~A() called for you on obkect pointed to by p
これは、 "デストラクタ" ではなく、 "デコンストラクタ" という名前が付けられます。
各クラスのデストラクタの中に、あなたは新しいして割り当てられている他のすべてのメンバ変数を削除する必要があります。
編集:明確にします:
あなたが持っていると言います
struct A {}
class B {
A *a;
public:
B () : a (new A) {}
~B() { delete a; }
};
class C {
A *a;
public:
C () : a (new A) {}
};
int main () {
delete new B;
delete new C;
}
何Bは内部もデストラクタで削除されますので、割り当てBのインスタンスを割り当てた後、削除は、クリーンでます。
しかし、それは(この場合、Cもデストラクタを持たない)を解放しないのインスタンスを割り当てるため、クラスCのインスタンスは、メモリリークが発生します。
あなたはいつものポインタ(A*
)を持っている場合は、デストラクタが呼び出されません(とA
インスタンスのメモリがどちらか解放されません)あなたはdelete
のデストラクタで明示的にB
ない場合を除きます。あなたはauto_ptr
のようなスマートポインタの自動破壊の外観をしたい場合。
あなたはBのデストラクタで自分自身を削除する必要があります。
class B
{
public:
B()
{
p = new int[1024];
}
virtual ~B()
{
cout<<"B destructor"<<endl;
//p will not be deleted EVER unless you do it manually.
}
int *p;
};
class D : public B
{
public:
virtual ~D()
{
cout<<"D destructor"<<endl;
}
};
あなたが行うとます:
B *pD = new D();
delete pD;
デストラクタがあなたの基底クラスが仮想キーワードを持っている場合にのみ呼び出されます。
次に、あなただけの〜B()が呼び出されることになる仮想デストラクタを持っていなかった場合。あなたは仮想デストラクタを持っているのでしかし、最初の〜D()が呼び出されます、そして、〜B()。
あなたが明示的に削除しない限り、ヒープに割り当てBまたはDのいかなるメンバーが割り当て解除されません。そして、それらを削除すると、同様に彼らのデストラクタを呼び出します。
私は思っていました。その理由は、私は、そのクラス(の#include「class.h」)の定義を含めるのを忘れていたことでした。私だけのような宣言が持っていた「クラスAを;」コンパイラはそれで幸せだったと私は、「削除」を呼び出してみましょう。
はありません。ポインタが削除されます。あなたはBのデストラクタで明示的に削除を呼び出す必要があります。
クラスAのオブジェクトのデストラクタは呼び出されます。クラスBのデストラクタでそのポインタを削除することを確認します。
オブジェクトで呼び出されたときに、削除何が起こるかについて少し詳細については、以下を参照してください。 http://www.parashift.com/c++-よくある質問-LITE / freestore-mgmt.html#FAQ-16.9 の
いいえ、それは「PTR削除;」行を削除し、(PoweRoyが語ったように)あなたが明示的に呼び出す必要があり、クラスAのためのデストラクタを呼び出すことはありません例に比較する...
#include <iostream>
class A
{
public:
A(){};
~A();
};
A::~A()
{
std::cout << "Destructor of A" << std::endl;
}
class B
{
public:
B(){ptr = new A();};
~B();
private:
A* ptr;
};
B::~B()
{
delete ptr;
std::cout << "Destructor of B" << std::endl;
}
int main()
{
B* b = new B();
delete b;
return 0;
}
は、
のようなものを持っていますclass B
{
A * a;
}
B * b = new B;
b->a = new A;
あなたがdelete b;
を呼び出す場合は、、何も起こりませんし、あなたがメモリリークを持っています。 delete b->a;
に思い出そうとするのは得策ではありませんが、他のカップルがあります。
B::~B() {delete a;}
これは、削除させていただきますBのデストラクタです。 (0であれば、それは削除何もしません。0ではありませんが、新しいからメモリを指していない場合は、ヒープの破損を取得します。)
auto_ptr<A> a;
...
b->a.reset(new A);
bがあるときにこの方法は、あなたはポインタとして持っていないが、むしろ、auto_ptrは<>(shared_ptrの<>だけでなく、または他のスマートポインタを行います)、それが自動的に削除されます。
これらのいずれかの方法でうまく機能し、私は両方を使用しました。