C ++での削除演算子と削除[]演算子


135

違いは何であるdeletedelete[]C ++の演算子が?



7
deleteとdelete []の問題は、スマートポインターが好きな理由の1つvector<>であり、可能な場合は常に配列の代わりに使用します。
David Thornley、2010年


@DavidThornleyスマートポインターを使用している場合でもstd::unique_ptr<int>(new int[3])、たとえば、delete未定義の動作である配列でregularを呼び出すため、たとえば、書き込みを行わないことを知る必要があるという意味で、違いを知る必要があります。代わりに使用する必要がありますstd::unique_ptr<int[]>
Arthur Tacca

回答:


150

deleteオペレータは、メモリの割り当てを解除するとして作成された単一のオブジェクトのデストラクタを呼び出しますnew

delete []オペレータはして作成されたオブジェクトの配列のためのメモリと呼び出しデストラクタの割り当てを解除しますnew []

使い方deleteによって返されたポインタ上new []delete []によって返されたポインタにnew未定義の動作結果。


3
intやchar(コンストラクタ/デストラクタなし)などのプリミティブ型のnew []配列でdeleteを使用すると、必ず未定義の動作も発生するのではないかと思います。プリミティブ型を使用する場合、配列サイズはどこにも保存されないようです。
thomiel 14

21
それが行われたときに何が起こるかを標準が定義していない場合、コンパイラーが実行したいことをコンパイラーが決定的に行う場合でも、定義は「未定義の動作」です。別のコンパイラーは、まったく異なることを行う場合があります。
Rob K 14

「char ** strArray」のようなC文字列の配列があると、このエラーが発生しました。私のように配列がある場合は、配列を反復処理して各要素を削除/解放してから、strArray自体を削除/解放する必要があります。私が持っている配列で「delete []」を使用しても機能しません(上記のコメントと回答で指摘されているように)、ITはデストラクタを呼び出し、実際には各スロットを解放しません。
Katianie 2016年

88

delete[]オペレータは、アレイを削除するために使用されます。deleteオペレータは、非配列オブジェクトを削除するために使用されます。これは、配列の要素または非配列オブジェクトのデストラクタを(最終的に)呼び出した後に、配列または非配列オブジェクトが占有していたメモリを削除するためにそれぞれ呼び出しoperator delete[]operator delete機能します。

以下に関係を示します。

typedef int array_type[1];

// create and destroy a int[1]
array_type *a = new array_type;
delete [] a;

// create and destroy an int
int *b = new int;
delete b;

// create and destroy an int[1]
int *c = new int[1];
delete[] c;

// create and destroy an int[1][2]
int (*d)[2] = new int[1][2];
delete [] d;

new配列を作成する(つまり、new type[]またはnew配列型構成に適用される)の場合、Standardはoperator new[]配列の要素型クラスまたはグローバルスコープでを検索し、要求されたメモリ量を渡します。必要以上に要求するN * sizeof(ElementType)場合があります(たとえば、要素の数を格納するため、後で削除するときに、実行するデストラクタ呼び出しの数がわかる)。operator new[]メモリ量の追加が別のを受け入れることをクラスが宣言するとsize_t、その2番目のパラメーターは割り当てられた要素の数を受け取ります。これは、必要な目的(デバッグなど)にこれを使用できます。

以下のためにnew非配列オブジェクトを作成すること、それが探しますoperator new要素のクラスまたはグローバルスコープで。要求されたメモリの量を渡します(正確にsizeof(T)常に)。

の場合はdelete[]、配列の要素クラスタイプを調べ、そのデストラクタを呼び出します。operator delete[]使用される関数は、要素タイプのクラスの関数です。または、グローバルスコープにない場合は使用されます。

delete場合、渡されたポインタが実際のオブジェクトのタイプの基本クラスである場合、基本クラスには仮想デストラクタが必要です(それ以外の場合、動作は未定義です)。基本クラスでない場合は、そのクラスのデストラクタが呼び出され、operator deleteそのクラスまたはグローバルのin operator deleteが使用されます。基本クラスが渡された場合は、実際のオブジェクト型のデストラクタが呼び出され、operator deleteそのクラスで見つかったものが使用さoperator deleteれます。存在しない場合は、グローバルが呼び出されます。operator deleteクラス内にタイプの2番目のパラメータがある場合、size_t割り当てを解除する要素の数を受け取ります。


18

これは、c ++のallocate / DE-allocateパターンの基本的な使用法 malloc/ freenew/ deletenew[]/delete[]

それらを対応して使用する必要があります。しかし、私は違いのために、この特定の理解を追加したいと思いますdeleteし、delete[]

1)単一のオブジェクトにdelete割り当てられたメモリの割り当てを解除するために使用されます

2)オブジェクトの配列にdelete[]割り当てられたメモリの割り当てを解除するために使用されます

class ABC{}

ABC *ptr = new ABC[100]

と言うとnew ABC[100]、コンパイラーは、割り当てる必要があるオブジェクトの数(ここでは100)に関する情報を取得でき、作成された各オブジェクトのコンストラクターを呼び出します

これに対応してdelete ptr、この場合に単純に使用すると、コンパイラーはポイントしているオブジェクトの数を認識せずptr、デストラクターの呼び出しと1つのオブジェクトのメモリの削除のみを行います(デストラクターの呼び出しと残りの99個のオブジェクトの割り当て解除を残します)。したがって、メモリリークが発生します。

delete [] ptrこの場合は使用する必要があります。


3
これが正解です。他の回答はどれも明確な違いについて言及していません。「したがって、この場合に単にdelete ptrを使用すると、コンパイラはptrが指しているオブジェクトの数を認識せず、デストラクタの呼び出しと1つのオブジェクトのみのメモリの削除を行います」
Don Larynx、2015年

1
Cで同じことをするにはどうすればよいですか?
Dogusウラル

@DogusUralなんで?Cにはデストラクタがないため、free()これとこれだけです。擬似デストラクタパターンを使用する場合は、forループを使用してオブジェクトごとに1回呼び出す必要があります。
コタウカス

@DonLarynxの正しい違いは、それらを混同すると不正プログラムが作成されることです。実装、破壊するオブジェクトの数を知っている場合と、そうでない場合があります。それが間違って呼ばれたことを知ることは許され、問題がどこにあるかを知らせるプログラムを中止します。
カレス

6

演算子deletedelete []はそれぞれ、newnew[]で作成されたオブジェクトを破棄するために使用され、コンパイラのメモリマネージャで使用可能なまま割り当てられたメモリに戻ります。

で作成されたオブジェクトnewは必ずで破棄する必要がありdelete、で作成された配列new[]はで削除する必要がありdelete[]ます。


2

私がこの質問をしたとき、私の本当の質問は、「2つの間に違いはありますか?ランタイムは配列サイズに関する情報を保持する必要がないので、どちらが意味するのかを見分けることができないのですか?」ということでした。この質問は「関連する質問」には表示されないので、私のような人を助けるために、ここでその答えを示します。「なぜdelete []演算子が必要なのですか?」


この中に戻ってくると入れてくれてありがとう。
Ziffusion

0

delete単一のポインターにdelete[]使用され、ポインターを介して配列を削除するために使用されます。 これは、理解を深めるのに役立ちます。


-6

まあ..多分それはあくまでも明示的なものだと思います。オペレーターdeleteとオペレーターdelete[]は区別されますが、deleteオペレーターはアレイを解放することもできます。

test* a = new test[100];
delete a;

また、このコードをチェックしたところ、メモリリークはありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.