9

Accelerated C++ の第 11 章で、著者は、配列を使用して std::vector の動作をエミュレートする Vector クラスを提示しています。これらはアロケータ クラスを使用してメモリ管理を処理します。関数の役割はuncreate、配列の各要素を破棄し、配列に割り当てられたスペースを解放することです。

template <class T> void Vec<T>::uncreate() {
  if (data) {

  // destroy (in reverse order) the elements that were constructed 
  iterator it = avail;
  while (it != data)
    alloc.destroy(--it);

  // return all the space that was allocated
  alloc.deallocate(data, limit - data); 
  }

  // reset pointers to indicate that the Vec is empty again 
  data = limit = avail = 0;
}

明らかに、割り当てられたスペースの割り当てを解除する必要があります。しかし、個々の要素も破壊する必要がある理由はよくわかりません。個々の要素を破壊せずにメモリのみを解放するとどうなるでしょうか?

4

2 に答える 2

13

トラブルに巻き込まれる可能性があるからです。C++ 標準の 3.8 章 (オブジェクトの有効期間) の段落 4 で、その理由が説明されています (私の強調):

プログラムは、オブジェクトが占有するストレージを再利用するか、非自明なデストラクタを使用してクラス型のオブジェクトのデストラクタを明示的に呼び出すことにより、任意のオブジェクトの有効期間を終了できます。自明でないデストラクタを持つクラス型のオブジェクトの場合、プログラムは、オブジェクトが占有するストレージが再利用または解放される前に、デストラクタを明示的に呼び出す必要はありません。ただし、デストラクタへの明示的な呼び出しがない場合、またはストレージを解放するために削除式 (5.3.5) が使用されていない場合、デストラクタは暗黙的に呼び出されてはならず、デストラクタによって生成される副作用に依存するすべてのプログラム未定義の動作があります。

これは、自明なデストラクタ (*) を持つオブジェクトまたはそれをまったく持たないオブジェクト (など) によって占有されているメモリで実行しても問題ないことを意味しますints。しかし、デストラクタで何らかの作業 (ネットワーク接続やファイルを閉じる、バッファをフラッシュする、メモリを解放するなど) を行う必要があるクラスのオブジェクトがメモリに含まれている場合、リソースをリークします (そして、正式には標準により、未定義の動作を呼び出します)。

(*) デストラクタは、それがコンパイラによって生成され、仮想ではなく、メンバーであるクラスのすべての非静的メンバーと直接基底クラスに自明なデストラクタがある場合、自明です。

于 2013-08-06T10:50:50.120 に答える