7

私はこのような構造体を持っています:

class Items 
{
private:
    struct item
    {
        unsigned int a, b, c;
    };
    item* items[MAX_ITEMS];
}

次のように、アイテムを「削除」したいとします。

items[5] = NULL;

そして、後で同じ場所に新しいアイテムを作成しました。

items[5] = new item;

delete[]これを片付けるために電話する必要がありますか?items[]それとも、コンパイルする前に配列の境界がわかっているので、これは必要ではないでしょうか?

そのポインターを NULL に設定することは有効ですか、それとも削除を呼び出す必要がありますか?

4

8 に答える 8

16

deleteNULL に設定する前に呼び出す必要があります。(NULL に設定する必要はありません。ポインターを削除した後に誤ってポインターを逆参照しようとした場合に、バグを減らすのに役立ちます。)

を使用するたびに、後で同じポインターでnew使用する必要があることに注意してください。deleteどちらか一方のみを使用しないでください。

また、new []とも同様ですが、やとは絶対に混ぜてdelete []はいけません。あなたの例では、(オブジェクトの配列を作成するのではなく)でオブジェクトを作成したので、(ではなく)でオブジェクトを削除する必要があります。new []deletenewdelete []newnew []deletedelete []

于 2009-01-12T01:04:56.117 に答える
6

Kluge が指摘したように、そのようにインデックス 5 でオブジェクトをリークします。しかし、これは手動で行うのではなく、内部でコンテナ クラスを使用するように思えますItemitemこれらのオブジェクトをポインターとして実際に格納する必要がない場合は、ポインターstd::vector<item>の配列の代わりに使用してMAX_ITEMSください。必要に応じて、ベクター要素を途中で挿入または削除することもできます。

オブジェクトをポインターとして格納する必要がある場合 (通常item、例とは異なり、構造体が実際にポリモーフィックである場合)、代わりに Boost::ptr_vector<item> をBoost.PtrContainerから使用できます。

例:

class Items {
private:
    struct item {
        unsigned int a, b, c;
    };
    std::vector<item> items;
}

if (items.size() > 5) // (just to ensure there is an element at that position)
    items.erase(items.begin() + 5); // no need to use operator delete at all
于 2009-01-12T01:13:30.453 に答える
1

明確にするために、「delete[]」の呼び出しについて言及しています。私はあなたが意味すると思いますdelete

これについて言及するのは、C++ にはoperator deleteとの 2 つの別個の演算子があるためoperator delete[]です。後者は、 で割り当てられたオブジェクトの配列を削除するために使用され、この場合は適用されoperator new[]ません。オブジェクトへのポインターの配列があります。これoperator newは、 を 1 回呼び出すのではなく、を繰り返し呼び出すことで初期化する必要がありますoperator new[]

私が本当に言おうとしているのは、あなたの の使用delete[]は紛らわしく、あいまいです。に変更しdeleteます。

于 2009-01-12T08:07:43.160 に答える
1

次のように、アイテムを「削除」したいとします。

項目[5] = NULL;

私は Visual Basic をほとんど知りませんが、それは Visual Basic プログラミングのイディオムのような匂いがします。なぜなら、"Set a = None" (または Null、よくわかりません) は、a が指すオブジェクトを削除する (または、COM の参照カウントをデクリメントするからです)。オブジェクト)。


他の誰かが指摘したように、次のいずれかを使用する必要があります。

delete items[5];
items[5] = newContent;

また:

delete items[5];
items[5] = NULL;

の後delete[5]、 に格納されているポインターの唯一の可能な使用法は、items[5]問題を引き起こすことです。さらに悪いことに、最初は機能していても、以前に*items[5]. これらが、C/C++ プログラミングを「興味深い」もの、つまり本当に面倒なものにしている原因です (私のように C が好きな人にとっても)。

書き込みdelete items[5];は無駄な書き込みを節約するだけですが、それは時期尚早の最適化です。

于 2009-01-12T01:50:00.473 に答える
1

関連する質問がいくつかあります。

  1. 投稿されたコードによると、配列自体はヒープに割り当てられていない限り、ヒープに割り当てられないstructため、配列にする必要はありませんdelete[]。で配列を作成した場合は、それnew[]が必要にdelete[]なります。
  2. 投稿されたコードは、配列から指されているオブジェクトがどのように割り当てられているかを示していません。これらのオブジェクトをスタックに割り当てる場合、それらを削除してはなりません(繰り返しますが、ポインタが指すオブジェクトがスコープ外になるとポインタが無効になるため、これはほとんどありません)。それらを (新規で) ヒープに割り当てた場合は、範囲外になったときにそれらを削除する必要があります。
  3. 他の人がすでに示唆しているように、コンテナー (特に STL コンテナー) とスマート ポインター (現時点では Boost からのポインターを意味します) を使用すると、生活はずっと楽になります。
于 2009-01-12T08:20:57.050 に答える
1

アイテムを削除するには:

アイテムを削除[5];

アイテムを削除した後、削除されたポインターを NULL に設定することをお勧めします。これにより、後で誤って再度削除してもエラーが発生しなくなります。

アイテム[5] = NULL

于 2009-01-12T01:14:34.960 に答える
0

C++ は私の得意分野ではありませんが、ポインタを に設定するとメモリ リークが発生することは間違いありませんNULL

EDIT:リークされているメモリは、配列内のポインタが指すメモリです。

于 2009-01-12T00:57:08.880 に答える
0

items[5] を NULL に設定しても、アイテムに関連付けられたメモリは削除されません。単にそのアイテムへのポインタが NULL に設定されるため、メモリ リークが発生します。

次のように呼び出してアイテムを削除できます。

delete items[5];

C++ には自動ガベージ コレクションがないため、不要になったメモリを削除する必要があります。

于 2009-01-12T00:59:57.563 に答える