まず、次のことを覚えておいてください。
- によって割り当てられたものは、によって
malloc
割り当てを解除する必要がありますfree
- 使用しないでください
malloc
- によって割り当てられたものは、によって
new
割り当てを解除する必要がありますdelete
- によって割り当てられたものは、によって
new[]
割り当てを解除する必要がありますdelete[]
delete
すべてに1つ、すべてに1new
つdelete[]
new[]
- 上記のいずれも使用しないでください
malloc
そうすれば、デストラクタがないと、によって割り当てられたメモリは解放されないと考えるのは正しいことです。上記のルールに従う場合は、割り当てを解除するためにfree
(ではなくdelete[]
)を使用する必要があります。
ClassX::~ClassX() { free(p); }
ただし、malloc
C ++はオブジェクトのコンストラクターを呼び出さないため、まずC ++で使用するべきではありません。使用する必要がありますnew
:
ClassX::ClassX() : p(new int) { }
// NOW we use delete since we used new (not delete[] since we didn't use new[])
ClassX::~ClassX() { delete p; }
ただし、その場合は、コピーコンストラクター、コピー代入演算子、ムーブ代入演算子、およびムーブ代入演算子を作成する必要があります。それでは、さらに良い方法を見てみましょう。
class ClassX{
private:
ClassX();
std::unique_ptr<int> p;
int i;
....
};
// we have to break rule #6 here
ClassX::ClassX() : p(new int) { }
これで、デストラクタを作成する必要がなくなります。デストラクタが呼び出されると、delete
作成したものが自動的に呼び出されるため、スマートポインタに処理させることができます。new
それは私たちを導きます...
あなたの他の質問:
それはmallocによって割り当てられたメモリを解放しますが、クラスのフィールド(つまり、iとp)に割り当てられたメモリは解放しませんか?
それは約1/4正しいです。i
とはクラスのメンバーであるためp
、囲んでいるクラスの割り当てが解除されると自動的に割り当てが解除され、クラス自体の場合は、デストラクタが呼び出されます。したがってdelete
、デストラクタを挿入するnew
と、i
によって割り当てられたメモリp
が処理され、自動的にクリーンアップされ、すべてが正常になります。(間違った割り当て解除機能を使用したため、1/4しか正しくありませんでした。)
つまり、スマートポインターを使用すると、オブジェクトが破棄されたときにスマートポインターのデストラクタが呼び出され、割り当てられたものが自動的に割り当て解除さnew
れます。だからあなたもそれについて心配する必要はありません。
これはすべて、クラスの一部としてダイナミックが本当に必要であることを前提としています。int
ただし、可能であれば、int
by値を格納する(ポインタを格納しない)ことをお勧めします。そうすれば、スマートポインタ、割り当て解除、またはその他のものをいじる必要がなくなります。