所以我们的讲师只是向我们展示了如何连接两个链表,然后继续向我们展示了示例,如果实施该示例将是错误的,我似乎不太了解为什么它不能很好地工作,因为它没有解释。如果我以这种方式连接两个链表,会出现什么问题:
template <typename T>
void LList<T>::concat(LList<T> const & list) {
end->next = list.start;
end = list.end;
}
答案 0 :(得分:6)
问题中使用的方法是错误的,因为它错误地共享了传输节点的Ownership。
list
拥有其节点。它维护并最终释放它们。通过将指向list
所拥有的节点的指针提供给接收链表,您现在将具有两个链表,它们引用并试图拥有同一组节点。如果以后修改list
,则将修改接收器,并可能使其处于不一致状态(例如,end
可能不再正确)。如果以后销毁list
,则list
销毁其节点后,接收方将指向无效内存。同样,list
通过修改或销毁接收器而处于不稳定状态。
这在某种程度上与The Rule of Three有关,这是我要利用“三则规则”所要求的副本构造函数。我将按值而不是作为引用传递list
,以便正确地复制它,然后将其节点列表(即源列表所拥有的节点的副本)移动到接收链接列表中。然后,您可以清理list
,以便安全销毁并在超出范围时使其死亡。这种方法可能会有点慢,但是几乎是万无一失的。请参见Copy and Swap Idiom,了解适用于赋值运算符的几乎相同的技巧。