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

当您为包含动态分配X(const T& other)的对象(在您的情况下可能是 a )编写复制构造函数时,您可能最终会写出这样的一行: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 回答