21

したがって、ポインターの配列へのポインターがあります。このように削除すると:

delete [] PointerToPointers;

ポインタへのポインタもすべて削除されますか?そうでない場合は、すべてのポインターをループして削除する必要がありますか、またはそれを行う簡単な方法はありますか? 私のgoogle-fuは、この質問に対する良い答えをくれないようです。

(ええ、ベクトルを使用する必要があることはわかっています。これは、学校での「C++ に追いつく」タイプの課題の 1 つです。)

4

7 に答える 7

30

はい、ポインタをループして、個別に削除する必要があります。

理由:他のコードに配列内のオブジェクトへのポインターがある場合はどうなりますか?C ++コンパイラは、それが正しいかどうかを認識しないため、明示的にする必要があります。

「より簡単な方法」として、2つの提案があります。(1)この目的のためにサブルーチンを作成して、少なくともコードを2回以上記述する必要がないようにします。(2)参照カウンターを持つオブジェクトの配列を保持する「スマートポインター」設計パラダイムを使用します。オブジェクトがコードによって参照されなくなると、オブジェクトは削除されます。

于 2008-09-07T03:24:13.833 に答える
20

ジェイソン・コーエンに同意しますが、ループでポインターを削除する必要がある理由については少し明確にすることができます。「新しい」または動的なメモリ割り当てごとに、メモリの割り当て解除を「削除」する必要があります。スマートポインターのように「削除」を非表示にできる場合もありますが、まだそこにあります。

int main()
{
  int *pI = new int;
  int *pArr = new int[10];

これまでのコードでは、動的メモリの 2 つのチャンクを割り当てました。1 つ目は単なる一般的な int で、2 つ目は int の配列です。

  delete pI;
  delete [] pArr;

これらの削除ステートメントは、「新しい」によって割り当てられたメモリをクリアします

  int ppArr = new int *[10];

  for( int indx = 0; indx < 10; ++indx )
  {
    ppArr[indx] = new int;
  }

このコードは、以前の両方の割り当てを行っています。最初に、動的配列に int 用のスペースを作成しています。次に、ループして、配列内の各スポットに int を割り当てる必要があります。

  for( int indx = 0; indx < 10; ++indx )
  {
    delete ppArr[indx];
  }
  delete [] ppArr;

このメモリを割り当てた順序と、逆の順序で割り当てを解除したことに注意してください。これは、delete [] ppArr; を実行した場合に発生するためです。最初に、他のポインターが何であるかを示す配列を失います。そのチャンクまたはメモリはシステムに戻されるため、確実に読み取ることができなくなります。

  int a=0;
  int b=1;
  int c=2;

  ppArr = new int *[3];

  ppArr[0] = &a;
  ppArr[1] = &b;
  ppArr[2] = &c;

これについても言及する必要があると思います。ポインターを操作しているからといって、それらのポインターが指すメモリが動的に割り当てられたわけではありません。つまり、ポインターがあるからといって、必ずしも削除する必要があるわけではありません。ここで作成した配列は動的に割り当てられますが、ポインターは int のローカル インスタンスを指します。これを削除する場合は、配列を削除するだけです。

  delete [] ppArr;

  return 0;

}

最終的に、動的に割り当てられたメモリは扱いにくい場合がありますが、スマート ポインターのように、または stl コンテナーを使用して安全にラップすることができます。

于 2008-09-07T18:36:41.957 に答える
4

通常の STL コンテナーに非常に近い構文を維持しながら、含まれているポインターを自動的に削除するコンテナーについては、ブースト ポインター コンテナーを参照してください。

于 2008-09-12T16:44:53.383 に答える
3

ポインターはほとんど単なるメモリ参照であり、気の利いた小さなセルフクリーニング .net オブジェクトではありません。各クラスに適切なデストラクタを作成すると、コード全体で大量のループを作成するよりも、削除が少しきれいになります。

于 2008-09-07T03:22:22.810 に答える
3

(疑似コード化された) 実世界の例を見てみましょう。次のようなクラスがあると想像してください。

class Street
{
    public:
        Street();
        ~Street();
    private:
        int HouseNumbers_[];
}

typedef *Street StreetSign;

道路標識の配列があり、道路標識の配列を削除しても、通りが自動的に削除されるわけではありません。彼らはまだそこにいます、レンガとモルタル、彼らを指し示す兆候はもうありません。通りへのポインターの特定のインスタンスを取り除きました。

ポインターの配列は (概念的に) 整数の配列に少し似ています。これは、さまざまなオブジェクトのメモリ位置を表す数値の配列です。それはオブジェクトそのものではありません。

ポインターの配列を削除すると、整数の配列を削除するだけです。

于 2010-09-29T13:43:45.453 に答える
1

恐れながら、ループオーバーする必要があると思います。

于 2008-09-07T03:20:25.670 に答える
0

なぜこれが混乱するほど長く答えられたのかわかりません。

ポインターの配列を削除すると、通常は int の配列に使用されていたメモリが解放されます。
オブジェクトへのポインターは、アドレスを含む整数です。

たくさんの住所を削除しましたが、オブジェクトはありません。

delete はメモリ空間の内容を気にせず、デストラクタを呼び出し、メモリを空きとしてマークします。

オブジェクトのアドレスの束を削除したことは気にせず、単に int を見るだけです。

そのため、最初に配列を循環する必要があります。すべての要素で削除を呼び出すと、配列自体のストレージを削除できます。

さて、私の答えはやや長くなりました... ....奇妙な... ;)

編集: ジェイソンの答えは間違っていません。コンパイラも c(++) の他のものも、他の場所で指されているものを削除することを気にしません。あなたはそれを行うことができます。削除されたオブジェクトを使用しようとする他のプログラム部分は、セグメンテーション違反を起こします。しかし、誰もあなたを妨げません。オブジェクトが他の場所で参照されている場合、オブジェクトへのポインターの配列を破棄することも問題になりません。

于 2009-04-15T16:25:39.860 に答える