1

私は次のクラスを持っています:

class Stack {
  struct Link {
    void* data;
    Link* next;
    void initialize(void* dat, Link* nxt);
  }* head;
public:
  void initialize();
  void push(void* dat);
  void* peek();
  void* pop();
  void cleanup();
};

pop方法は次のとおりです。

void* Stack::pop() {
  if(head == 0) return 0;
  void* result = head->data;
  Link* oldHead = head;
  head = head->next;
  delete oldHead;
  return result;
}

oldHeadはへのポインタでありstruct Link、メンバーとしてvoidポインタを持っています。それで、削除することによって、oldHead私はそのvoidポインターを暗黙的に削除しているのですよね?

BruceEckelによるThinkinginC ++を読んでいますdeleteが、ポインタの種類を知る必要があるため、voidポインタを削除しても適切にクリーンアップされないと言われています。

このコードは暗黙的にvoidポインターdataを削除しているので、誰かがvoidポインターを削除するこの(暗黙の)方法がwithで削除するのと異なる理由を説明できますかdelete <void pointer>

4

4 に答える 4

2

あなたの用語はあいまいさを引き起こしていますが、説明させてください。あなたが持っているとしましょう:

struct foo
{
    void* bar;
};

a のfoo存続期間が終了すると、 abarも存在しなくなります。あなたが持っている場合:

{
    foo f = { new int; }
}

new int決して削除されないように、あなたはリークしました。同様に、次の場合:

{
    foo* f = new foo;
    f->bar = new int;
    delete f;
}

delete fが実行されると、f指しているものの存続期間が終了するだけなので (上記で自動的に起こったのと同じように)、 ergobarは存在しなくなり、new intは削除されないため、まだリークしています。

要約すると、オブジェクトの有効期間が終了すると、ポインターでdeleteあるメンバーに対して呼び出されません。

したがって、 で delete を呼び出すと、上記Linkと同じ状況になります。メモリを削除して存在を停止させますが、それが指しているものを実際に削除するわけではありません。barfooLinkdata

于 2010-07-23T18:16:18.317 に答える
0

void ポインタの削除に関する問題の 1 つは、デストラクタで何かを指している場合に発生します。

#include <iostream>

struct foo
{
    ~foo() { std::cout << "important work" << std::endl; }
};

int main()
{
    foo *f = new foo;

    void *v = f;

    delete v;
}

上記のコード サンプルを実行すると、デストラクタが呼び出されないことがわかります。

于 2010-07-23T18:30:19.353 に答える
0

を削除Linkしても、その void* メモリ空間は削除されません。割り当てられたメモリを削除するデストラクタを定義する必要があります。新しいものごとに 1 つの削除が必要です。Link-struct のこの例は、を削除するデストラクタを追加することdataです。あなたの仮定が正しければ、nextも削除され、リンクされたリスト全体が削除され、ひどい動作になります。

ポインタに対して delete を呼び出すと、指定された型のデストラクタが呼び出されます。その型にデストラクタがない場合、そのようなデストラクタは呼び出されません。これは、デストラクタを持たない void ポインタの場合です。継承の場合、階層内の最も深いクラスでデストラクタが呼び出されるように、デストラクタは常に仮想である必要があります。ポインターを間違った型にキャストしても、メモリは正しく解放されます。デストラクタが正しく呼び出されないだけです。

于 2010-07-23T18:14:47.003 に答える
0

「その void ポインターを暗黙的に削除していますよね?」

削除すると、ポインター自体が削除されますoldHeadtargetを削除したり解放したりしていません。これは、あなたが望んでいるように見えdelete、ポインタを呼び出すときに起こることです。

(なぜそうなるのかを理解するために、構造体の外部の何かを指すポインターを使用して構造体を定義する可能性があると考えてくださいvoid*。構造体が削除されたからといって、ターゲットを解放したくないでしょう。)

于 2010-07-23T18:15:05.140 に答える