所以我们的讲师只是向我们展示了如何连接两个链表,但随后又向我们展示一个如果实现就会出错的例子,我似乎不太明白为什么它不能很好地工作,因为它没有解释。如果我用这种方式连接两个链表会有什么问题:
template <typename T>
void LList<T>::concat(LList<T> const & list) {
end->next = list.start;
end = list.end;
}
问题中使用的方法是错误的,因为它错误地共享了已转移节点的所有权。
CCD_ 1拥有其节点。它维护并最终释放它们。通过将指向list
拥有的节点的指针提供给接收链表,现在将有两个链表引用并试图拥有同一组节点。如果以后修改list
,则会修改接收器,并可能使其处于不一致的状态(例如,end
可能不再正确(。如果稍后销毁list
,则在list
销毁其节点后,接收器将指向无效内存。同样地,CCD_ 7通过修改或破坏接收器而处于不稳定状态。
这在一定程度上与三规则有关,正是三规则所需的复制构造函数,我会利用它来摆脱这种混乱。我会按值而不是作为引用传递list
,以便它被正确复制,然后将其节点列表(源列表所拥有的节点的副本(移动到接收链表中。然后,您可以清理list
,这样就可以安全地销毁它,并在它超出范围时让它死去。这种方法可能有点慢,但几乎是万无一失的。请参阅复制和交换习语,了解应用于赋值运算符的几乎相同的技巧。