web-dev-qa-db-ja.com

削除コマンドは、C ++のポインターに対して、メモリに対して実際に何をしますか?

重複の可能性:
C++ delete-オブジェクトは削除されますが、データには引き続きアクセスできますか?
ローカル変数のメモリはそのスコープ外でアクセスできますか?

deleteで割り当てられたメモリを解放したいときに、newが実際に何をするのかわかりません。 C++ Premiereの本では、次のように書かれています。

これにより、psポインタが指すメモリが削除されます。ポインタps自体は削除されません。たとえば、psを再利用して、別の新しい割り当てを指すことができます。 newの使用とdeleteの使用のバランスを常にとる必要があります。そうしないと、メモリリークが発生する可能性があります。つまり、割り当てられているが使用できなくなったメモリです。メモリリークが大きくなりすぎると、より多くのメモリを探しているプログラムが停止する可能性があります。

したがって、私が理解しているように、deleteは、ピンターが指すメモリ内の値を削除する必要があります。しかし、そうではありません。これが私の実験です:

int * ipt = new int;   // create new pointer-to-int

cout << ipt << endl;   // 0x200102a0, so pointer ipt points to address 0x200102a0
cout << *ipt << endl;  // 0, so the value at that address for now is 0. Ok, nothing was assigned
*ipt = 1000;     // assign a value to that memory address
cout << *pt << endl;   // read the new value, it is 1000, ok
cout << *((int *) 0x200102a0) << endl;   // read exactly from the address, 1000 too

delete ipt;   // now I do delete and then check
cout << ipt << endl;  // 0x200102a0, so still points to 0x200102a0
cout << *ipt << endl;  // 1000, the value there is the same
cout << *((int *) 0x200102a0) << endl;    // 1000, also 1000 is the value

では、deleteは実際に何をするのでしょうか?

17
Green

メモリは、物を入れるためのたくさんの箱がある大きな倉庫と考えてください。 「新品」と呼ぶと、倉庫のスタッフはあなたのニーズに十分な大きさの未使用の箱を見つけ、その箱をあなたが所有しているものとして記録し(他の人に渡されないように)、あなたが置くことができるようにその箱の番号を教えてくれますそれにあなたのもの。この番号が「ポインタ」になります。

ここで、そのポインターを「削除」すると、逆のことが起こります。倉庫のスタッフは、この特定のボックスが再び使用可能になることに注意します。実際の倉庫スタッフとは異なり、彼らは箱を使って何もしていません。そのため、「削除」後に箱を調べると、古いものが表示される場合があります。または、その間にボックスが再割り当てされた場合は、他の誰かのものが表示される可能性があります。

技術的には、プールに戻した後は箱を覗き込むことはできませんが、これは鍵や警備員がいないやや奇妙な倉庫なので、やりたいことは何でもできます。ただし、ボックスの新しい所有者に問題が発生する可能性があるため、ルールに従うことが期待されます。

48

deleteステートメントの後にポインターを逆参照するとすぐに、実験にはundefined behaviorがあります。すべてが起こる可能性があるため、実験はかなり価値がありません。

deletedelete[]ではない)は何をしますか?引数が指すstorageの割り当てを解除します。これにより、その場所に格納されているオブジェクトのデストラクタが実行されます。削除されたストレージにアクセスすると、未定義の動作がトリガーされます(多くの場合、segmentation fault)。メモリが実際にオペレーティングシステムなどに戻されるという保証はありません。

7
pmr

delete-の後にポインタを逆参照することは未定義の動作であるため、何かが起こる可能性があります

通常、deleteはメモリを解放済みとしてマークし、後で再利用できるようにしますが、これは複雑なトピックです。

経験則:決してnewdeleteを直接使用しないでください(何らかの理由で標準に欠けているmake_uniqueを実装する場合を除く)。 RAIIを使用します。

5
user1203803

deleteは、newを介した後のリクエストでメモリを使用できるようにします。コンテンツにスクランブルをかけるかどうかは未定義です。内容をそのままにしておく方が速いので、リリースモードではメモリがまだ「利用可能」であるように見えるでしょう。デバッグモードでは、マジックナンバーでスクランブルされる可能性があります。

ここで発生しているのは、C++では「未定義の振る舞い」と呼ばれています。この場合、未定義の動作は、メモリの存続期間が終了した後にメモリにアクセスすることによって発生します。ただそれをしないでください。

5
fredoverflow

delete演算子は、new演算子を使用して以前に割り当てられたメモリを解放します。これは、たとえば、プログラムの後半でnewを別に使用する場合などに、メモリをシステムで使用できるようになったことを意味します。ただし、メモリ内のデータはクリアされますnot。ポインタは引き続きメモリ内の同じアドレスを指しますが、そのブロックにアクセスすると、未定義の動作が発生します。

ポインタをNULLした後、nullptr(またはC++ 11ではdelete)に設定することをお勧めします。後続のdeletesは無害になります。

3
Code-Apprentice

deleteはメモリをシステムに戻します-基本的に、それはもはやあなたのプログラムのために予約されていません。これは、メモリ内の値がすぐに上書きされることを意味するわけではありませんが、deleteが実行された後はいつでもcouldになります。ほとんどの場合、同じメモリが独自のプログラムで将来使用するために再割り当てされます。

3
Turix