1

ポインターを回避するのに苦労しています。ここにいる誰かが、コピー コンストラクターをより直感的に概念化できると想像できます。単純にポインターを相互に割り当てること (浅いコピー) ができないことは理解していますが、実際にオブジェクトをコピーするのに苦労しています。

これが私のコードのサンプルです:

class LList {
    /* stuff */

    private:
        struct node {
            node   *next;
            node   *prev;
            int    *o;
        };

        node   *first; // The pointer to the first node (NULL if none)
        node   *last;  // The pointer to the last node (NULL if none)
}

助けてくれてありがとう!

4

3 に答える 3

3

動的に割り当てられた(おそらくあなたの場合は a ) を含むX(const T& other)オブジェクトのコピー コンストラクター を作成する場合、次のような行を作成することになる可能性があります。XT* pNode*

p = new T(*other.p);

これにより、コピーしているオブジェクトが指すオブジェクトのコピーが作成され、そのオブジェクトのディープ コピーが作成されます。あなたの場合、これはリストの再帰的なディープコピーになります。

于 2012-12-02T10:15:55.970 に答える
1

リンク リストのディープ コピーを作成することは、同じデータ値を持つ新しいリンク リストを作成することと同じです。

だから、あなたはできる

  • 現在のリストをトラバースする
  • 各ノードからの情報の抽出
  • それを新しいノードに渡します(基本的に、リストポインター以外のすべてをコピーします)
  • それを新しいリスト (ディープ コピー) に追加します。

あなたの場合、o を参照し、データを抽出し、新しいブロックを割り当て、データを割り当ててから、それを新しいノードに追加する必要があります。

于 2012-12-02T10:11:32.903 に答える
1

テストされていませんが、これはあなたが得ているアイデアの一部を表しているかもしれません. ただし、代わりに使用してみstd::listます:)コピー代入演算子と、適切に割り当て/割り当て解除するデストラクタを追加する必要がありますここを参照してください。

template<typename T>
struct ListNode {
    ListNode *next, *prev;
    T value;

    ListNode(const T &val): value(val), next(0), prev(0) {}

    // copy constructor
    ListNode(const ListNode &other): value(other.value) {
        if(other.next)
           append(new ListNode(*other.next));
    }

    void append(ListNode &n) {
        next = &n; n.prev = this;
    }
};

あなたがポインタである場合、ポインタメンバーが上記でコピーさvalueれたのと同じ方法でそれをコピーしたいと思うでしょう:next

    // copy constructor
    ListNode(const ListNode &other): value(new T(*other.value)) {
        if(other.next)
           append(new ListNode(*other.next));
    }

したがって、上記のリストの例では、次のようなことを試すことができます。

class LList {
    LList(): first(0), last(0) {}

    // copy constructor
    LList(const LList &other):
        first(0),
        last(0)
    {
        if(other.first) {
          first = new node(*other.first);
          // find last item
          last = first;
          while(last->next) last = last->next;
        }
    }

    ~LList() {
       if(first) delete first;
    }

    // TODO: copy assignment operator

private:
    struct node {
        node(int val): next(0), prev(0), o(new int(val)) {}
        // copy constructor
        node(const node &other): next(0), prev(0), o(*other.o)
        {
            if(other.next) {
               next = new node(*other.next);
               next->prev = this;
            }   
        }

        ~node() {
          delete o;
          if(next) delete next;
        }
        // TODO: copy assignment operator

        node   *next;
        node   *prev;
        int    *o;
    };

    node   *first; // The pointer to the first node (NULL if none)
    node   *last;  // The pointer to the last node (NULL if none)
};

テストされていませんが、それがアイデアです...コンストラクターは、次のアイテムを操作することで再帰的に機能します。リンクで説明されているように、「TODO」項目は重要です。また、スマート ポインターを調べることもできます。スマート ポインターは、物を削除することを覚えておく必要がなくなり、例外の安全性が向上し、通常は生のポインターよりもはるかに安全なオプションです。

于 2012-12-02T10:15:42.850 に答える