我很难绕过指针。我可以想象这里有人可以更直观地概念化复制构造函数。我知道你不能简单地指定彼此的指针(浅拷贝),但我实际上很难复制对象。
以下是我的代码示例:
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)
}
感谢您的帮助!
答案 0 :(得分:3)
当您为对象X(const T& other)
编写复制构造函数时,X
包含动态分配的T* p
(在您的情况下可能是Node*
),你最终可能会写这样一句话:
p = new T(*other.p);
这将创建您正在复制的对象所指向的对象的副本,从而为您提供该对象的深层副本。在您的情况下,这将最终导致列表的递归深度复制。
答案 1 :(得分:1)
创建链表的深层副本相当于创建具有相同数据值的新链表。
所以,你可以
在您的情况下,您需要尊重o,提取数据,分配新块,分配数据,然后将其添加到新节点。
答案 2 :(得分:1)
未经测试,但这可能表达了您所获得的想法的一部分。我尝试使用std::list
代替:) 您应该添加一个复制赋值运算符和一个适当分配/解除分配的析构函数。请参阅here。
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”项很重要。您可能还想查看智能指针 - 它们不需要记住删除内容,提高异常安全性,并且通常比原始指针更安全。