103

コンテキスト: 私はポインターについて頭を包み込もうとしています. 数週間前に学校でそれらを見たばかりで、今日練習中にばかげたものに出くわしました? 問題、それはあなたにとって非常に簡単かもしれませんが、私はプログラミング経験がほとんどありません.

SO でポインターの削除に関するかなりの数の質問を見てきましたが、それらはすべて「単純な」ポインター (または適切な用語が何であれ) ではなく、クラスの削除に関連しているようです。ここに私がしようとしているコードがあります走る:

#include <iostream>;

using namespace std;

int main() {
  int myVar,
      *myPointer;

  myVar = 8;
  myPointer = &myVar;

  cout << "delete-ing pointers " << endl;
  cout << "Memory address: " << myPointer << endl;

  // Seems I can't *just* delete it, as it triggers an error 
  delete myPointer;
  cout << "myPointer: " << myPointer << endl;
  // Error: a.out(14399) malloc: *** error for object 0x7fff61e537f4:
  // pointer being freed was not allocated
  // *** set a breakpoint in malloc_error_break to debug
  // Abort trap: 6

  // Using the new keyword befor deleting it works, but
  // does it really frees up the space? 
  myPointer = new int;
  delete myPointer;
  cout << "myPointer: " << myPointer << endl;
  // myPointer continues to store a memory address.

  // Using NULL before deleting it, seems to work. 
  myPointer = NULL;
  delete myPointer;
  cout << "myPointer: " << myPointer << endl;
  // myPointer returns 0.

}

だから私の質問は:

  1. 最初のケースが機能しないのはなぜですか? ポインターを使用して削除する最も簡単な使用法と思われますか? エラーは、メモリが割り当てられていないことを示していますが、「cout」はアドレスを返しました。
  2. 2 番目の例では、エラーは発生していませんが、myPointer の値を計算してもメモリ アドレスが返されますか?
  3. #3は本当に機能しますか?私にはうまくいくようです.ポインタはもはやアドレスを保存していません.これはポインタを削除する適切な方法ですか?

長い質問で申し訳ありませんが、これをできるだけ明確にしたかったのですが、繰り返しますが、私はプログラミングの経験がほとんどないので、誰かが素人の言葉を使ってこれに答えることができれば、それは大歓迎です!

4

6 に答える 6

189

1 & 2

myVar = 8; //not dynamically allocated. Can't call delete on it.
myPointer = new int; //dynamically allocated, can call delete on it.

最初の変数がスタックに割り当てられました。new演算子を使用して (ヒープ上で) 動的に割り当てたメモリに対してのみ delete を呼び出すことができます。

3.

  myPointer = NULL;
  delete myPointer;

上記はまったく何もしませんでした。ポインターが NULL を指していたため、何も解放されませんでした。


次のことはすべきではありません。

myPointer = new int;
myPointer = NULL; //leaked memory, no pointer to above int
delete myPointer; //no point at all

NULL を指し、リークしたメモリ (割り当てた新しい int) を残しました。指していたメモリを解放する必要があります。もう割り当てられたものにアクセスする方法がないnew intため、メモリ リークが発生します。


正しい方法:

myPointer = new int;
delete myPointer; //freed memory
myPointer = NULL; //pointed dangling ptr to NULL

より良い方法:

C++ を使用している場合は、生のポインターを使用しないでください。代わりに、これらのことをほとんどオーバーヘッドなしで処理できるスマート ポインターを使用してください。C++11 にはいくつかの.

于 2012-11-04T22:06:52.383 に答える
27

ポインターがどのように機能するかを完全に理解していないと思います。
あるメモリを指しているポインタがある場合、理解しなければならないことが 3 つ
あり
ます
。動的に割り当てられたメモリを削除する必要があります (使用されたnew演算子)。

想像:

int *ptr = new int; 
// ptr has the address of the memory.
// at this point, the actual memory doesn't have anything.
*ptr = 8;
// you're assigning the integer 8 into that memory.
delete ptr;
// you are only deleting the memory.
// at this point the pointer still has the same memory address (as you could
//   notice from your 2nd test) but what inside that memory is gone!

あなたがしたとき

ptr = NULL;
// you didn't delete the memory
// you're only saying that this pointer is now pointing to "nowhere".
// the memory that was pointed by this pointer is now lost.

C++ では、 をdelete指すポインターを試すことができますnullが、実際には何もせず、エラーは発生しません。

于 2012-11-05T00:00:39.987 に答える
13

ポインターは、削除する必要がないという点で通常の変数と似ています。これらは、関数実行の終了時および/またはプログラムの終了時にメモリから削除されます。

ただし、ポインターを使用して、たとえば次のようにメモリの「ブロック」を割り当てることができます。

int *some_integers = new int[20000]

これにより、20000 個の整数にメモリ空間が割り当てられます。スタックのサイズには制限があり、スタック オーバーフロー エラーを発生させずに「int」を大量にロードしたい場合があるため、便利です。

new を呼び出すときは常に、プログラムの最後で「削除」する必要があります。そうしないと、メモリ リークが発生し、割り当てられたメモリ領域の一部が他のプログラムで使用できるように返されないためです。これをする:

delete [] some_integers;

それが役立つことを願っています。

于 2012-11-04T22:15:35.513 に答える
8

C++ にはルールがあり、すべてのnewにはdeleteがあります。

  1. 最初のケースが機能しないのはなぜですか? ポインターを使用して削除する最も簡単な使用法と思われますか? エラーは、メモリが割り当てられていないことを示していますが、「cout」はアドレスを返しました。

new が呼び出されることはありません。したがって、cout が出力するアドレスは、myVar のメモリ ロケーションのアドレス、またはこの場合は myPointer に割り当てられた値です。書くことによって:

myPointer = &myVar;

あなたは言う:

myPointer = myVar のデータが格納されているアドレス

  1. 2 番目の例では、エラーは発生していませんが、myPointer の値を計算してもメモリ アドレスが返されますか?

削除されたメモリ位置を指すアドレスを返します。最初にポインターを作成してその値を myPointer に割り当て、2 番目にポインターを削除し、3 番目にそれを出力するためです。したがって、myPointer に別の値を割り当てない限り、削除されたアドレスは残ります。

  1. #3は本当に機能しますか?私にはうまくいくようです.ポインタはもはやアドレスを保存していません.これはポインタを削除する適切な方法ですか?

NULL は 0 に等しいので、0 を削除するので、何も削除しません。そして、あなたがしたので、それが 0 を出力するのは論理です:

myPointer = NULL;

等しい:

myPointer = 0;
于 2012-11-04T22:08:29.073 に答える
4
  1. スタックに割り当てられた変数を削除しようとしています。あなたはこれを行うことはできません
  2. ポインターを削除しても、実際にはポインターが破棄されるわけではなく、占有されているメモリが OS に返されます。メモリが別の変数に使用されるか、その他の方法で操作されるまで、アクセスできます。そのため、削除後にポインターを NULL (0) に設定することをお勧めします。
  3. NULL ポインターを削除しても、何も削除されません。
于 2012-11-04T22:11:40.417 に答える
2
int value, *ptr;

value = 8;
ptr = &value;
// ptr points to value, which lives on a stack frame.
// you are not responsible for managing its lifetime.

ptr = new int;
delete ptr;
// yes this is the normal way to manage the lifetime of
// dynamically allocated memory, you new'ed it, you delete it.

ptr = nullptr;
delete ptr;
// this is illogical, essentially you are saying delete nothing.
于 2012-11-04T22:15:46.150 に答える