3

リスト内のデータがポインターである双方向リンクリストの実装について少し混乱しています。

リンク リスト クラスのプライベート部分は次のようになります。

 private:
    struct node {
      node* next;
      node* prev;
      T* o;
    };
    node* first; // The pointer to the first node (NULL if none)
    node* last;  // The pointer to the last node (NULL if none)
    unsigned int size_;

ご覧のとおり、このリストは単なる古いオブジェクトではなく、オブジェクトへのポインターでいっぱいです。

仕様書には以下の記述があります。

このリストは、含まれている型 T にわたってテンプレート化されていますが、T のインスタンスではなく、T へのポインターのみを挿入および削除することに注意してください。これにより、Dlist 実装は、挿入されたオブジェクトを所有していることを認識し、リストコピーされ、リストが破棄された場合はそれらを破棄する必要があります。

私の現在の insertFront(T* o) の実装は次のとおりです。

void Dlist::insertFront(T* o) {
  node* insert = new node();
  insert->o = new T(*o); 
  insert->next = first;
  insert->prev = last;
  first = insert;
}

しかし、これは間違っているようです。T にコピー コンストラクターがない場合はどうなるでしょうか。そして、これはどのようにしてリスト内のオブジェクトの唯一の所有権を保証するのでしょうか?

私はただできるでしょうか:

insert->o = o;

次のような場合、これは安全ではないようです。

Object* item = new Object();
dlist.insertFront(item);
delete item;

次に、リストのアイテムも破棄されます。これは正しいです?私の理解はどこかずれていますか?

読んでくれてありがとう。

注: これは宿題のように見えますが、そうではありません。私は実際には Java 開発者であり、古い学校のプロジェクトを実行してポインタのスキルを磨いています。

4

1 に答える 1

4

ポインターのコンテナーがある場合、次の2つの使用シナリオのいずれかがあります。

  1. コンテナーにポインターが与えられ、コンテナーは、含まれている構造が削除されたときにポインターを削除する責任を負います。

  2. ポインタはコンテナに与えられますが、呼び出し元が所有します。呼び出し元は、ポインターが不要になったときにポインターを削除する責任を負います。

上記の1番は非常に簡単です。

番号2の場合、コンテナの所有者(おそらく呼び出し元も)は、アイテムを削除する前に、コンテナからアイテムを削除することが期待されます。

3番目のオプションは意図的に省略しました。これは、実際には最初のコード例で採用したオプションです。つまり、新しいアイテムを割り当ててコピーします。私がそれを省略した理由は、発信者がそれを行うことができるからです。

それを除外するもう1つの理由は、非ポインター型をとることができるコンテナーが必要になる場合があるためです。T*代わりに常にを使用してポインタである必要があるT場合は、希望するほど柔軟ではない可能性があります。強制的にポインタにする必要がある場合もありますが、コンテナに対してこれを行うための(頭のてっぺんからの)使用法は考えられません。

ユーザーがDlist<MyClass*>代わりに宣言することを許可するDlist<MyClass>と、そのリストの所有者は、ポインターを使用していることを暗黙的に認識し、これにより、ユーザーは上からシナリオ2を想定するようになります。

とにかく、ここにいくつかの解説付きのあなたの例があります:


1.T非常に正当な理由がない限り、新しいアイテムを割り当てないでください。その理由は単にカプセル化である可能性があります。これはすべきではないと前述しましたが、必要な場合もあります。コピーコンストラクターがない場合、クラスはおそらくプレーンオールドデータです。コピーが簡単でない場合は、三つのルールに従う必要があります。

void Dlist::insertFront(T* o) {
  node* insert = new node();
  insert->o = new T(*o);         //<-- Follow rule of three
  insert->next = first;
  insert->prev = last;
  first = insert;
}

2.これはあなたが通常行うことです

insert->o = o;

3.挿入後にアイテムを削除してはなりません。所有権をコンテナに渡すか、あなたもコンテナもそれを必要としなくなったときにアイテムを削除します。

Object* item = new Object();
dlist.insertFront(item);
delete item;                     //<-- The item in the list is now invalid
于 2012-11-23T01:17:12.537 に答える