2

deleteC++ では、演算子が配列と共に使用されると、それを「破棄」し、使用したメモリを解放することを理解しています。しかし、これが行われるとどうなりますか?

私のプログラムは、再利用のために解放されたヒープの関連部分をマークオフして、続行すると考えました。

しかし、配列の最初の要素が null に設定され、他の要素は変更されていないことに気付きました。これはどのような目的に役立ちますか?

int * nums = new int[3];
nums[0] = 1;
nums[1] = 2;

cout << "nums[0]: " << *nums << endl;
cout << "nums[1]: " << *(nums+1) << endl;

delete [] nums;

cout << "nums[0]: " << *nums << endl;
cout << "nums[1]: " << *(nums+1) << endl;
4

3 に答える 3

19

delete[]が呼び出されると、次の 2 つのことが起こります。

  1. 配列が非自明なデストラクタを持つ型の場合、デストラクタは配列内の各要素に対して逆の順序で呼び出されます
  2. 配列が占有していたメモリが解放されます

呼び出し後に配列が占めていたメモリにアクセスするとdelete、未定義の動作が発生します (つまり、何かが起こる可能性があります。データがまだそこにある可能性があります。または、データを読み取ろうとするとプログラムがクラッシュする可能性があります)。

于 2010-08-11T01:05:20.850 に答える
1

NULLである理由は、ヒープの実装次第です。

考えられる理由のいくつかは、空き領域の追跡に領域を使用していることです。次の空きブロックへのポインタとして使用している可能性があります。空きブロックのサイズを記録するために使用している可能性があります。新規/削除デバッグ追跡用にシリアル番号を書き込んでいる可能性があります。

それはそれのように感じるので、それは単にNULLを書いている可能性があります。

于 2010-08-11T01:19:58.090 に答える
0

誰かが. int* nums = new int[3]_ コンパイラは、使用したい任意の手法を使用できますが、一般的な手法が 2 つあります。3nums

によって生成されるコードはnums = new int[3]、数値3を静的な連想配列に格納する場合があります。この配列では、ポインターnumsがルックアップ キーとして使用され、数値3が関連付けられた値になります。によって生成されたコードdelete[] numsは、連想配列内のポインターを検索し、関連する size_t を抽出してから、連想配列からエントリを削除します。

によって生成されたコードはnums = new int[3]、追加の sizeof(size_t) バイトのメモリ (場合によってはいくつかのアライメント バイトを加えたもの) を割り当て、最初のオブジェクト3の直前に値を配置する場合があります。int次に、最初のオブジェクトの前 (つまり の前) の固定オフセットを調べてdelete[] nums見つけ、割り当ての先頭 (つまり の前の固定オフセットから始まるメモリのブロック) から始まるメモリの割り当てを解除します。3int*num*nums

どちらの技術も完璧ではありません。いくつかのトレードオフを次に示します。

連想配列の手法は時間がかかりますが、より安全です。誰かが[]物の配列の割り当てを解除するときに を忘れた場合、(a) 連想配列のエントリがリークし、(b) 配列の最初のオブジェクトだけが破棄されます。これは重大な問題である場合もそうでない場合もありますが、少なくともアプリケーションがクラッシュすることはないかもしれません。

オーバーアロケーション手法は高速ですが、より危険です: 誰かが言うdelete numsべき場所を言った場合delete[] nums、operator に渡されるアドレスはdelete(void* nums)有効なヒープ割り当てではなくなります — 少なくともsizeof(size_t)有効なヒープ割り当ての後のバイトになります。これにより、ヒープが破損する可能性があります。- C++ FAQ

于 2010-08-11T02:24:21.923 に答える