使用 std::unique_ptr 的双向链表
Posted
技术标签:
【中文标题】使用 std::unique_ptr 的双向链表【英文标题】:Doubly Linked List Using std::unique_ptr 【发布时间】:2013-03-01 08:04:27 【问题描述】:有人建议实施吗?前几天我在家里试过这个,发现移动语义太难建立一个先前的链接或简单的链表。如果使用 std::unique_ptr 制作树,则很容易。当然,由于复制/分配,std::shared_ptr 可以轻松实现这个问题。那么怎么样呢?
【问题讨论】:
为什么每个人都投票关闭? 我投票赞成关闭,因为我没有看到 OP 的任何努力。没有代码发布 OP 自己尝试过的内容。 @Nawaz 这并不意味着它“不是一个真正的问题”。我会说“这个问题没有表现出任何研究努力”,但第二句话又说他花时间尝试了一些东西。但这并不是关于为什么他的代码的问题,所以我看不出为什么这是相关的。 这不是一个很接近的问题,这是一个很好的问题。 您的意思是只使用unique_ptr
?对我来说似乎是不可能的,因为在双向链表中你有两个指向每个元素的指针,因此它们不能同时是unique_ptr
s。另一种选择是列表,其中next
是unique_ptr
s,而last
是普通的旧指针 - 乍一看我没有看到太多问题。
【参考方案1】:
由于问题已重新打开,我将发表我的评论作为我认为的答案:
如果你的意思是使用 only unique_ptr
,那将是不可能的,因为在双向链表中你有 两个 指向每个元素的指针,因此它们不能都是 unique_ptrs。 (这会以某种方式与 unique 部分相矛盾......)
为了澄清,让我们考虑三个元素的列表:A <-> B <-> C
这里A
将包含一个unique_ptr next
,指向B
,因此拥有B
。 C
将有一个 unique_ptr prev
,同时指向 B
- 并拥有它。拥有同一个对象的两个 unique_ptr
s 违反了 unique_land 定律,由于unique_ptr
的只能移动属性,您必须付出邪恶的努力才能实现它。
替代方法是一个列表,其中next
指针是unique_ptrs
,而last
指针是普通的旧 C 指针 - 我没有看到太多问题,所以我不认为这是你想要什么。
但是如果您有类似“半唯一列表”的想法,请提供一些代码并告诉我们您有什么问题 - 我们很乐意提供帮助 :)
【讨论】:
没有考虑半唯一列表。我可以通过 new easy 使用动态内存从 C 指针构建双向链表。使用 std::shared_ptr 提供实现也很容易。这不是问题。我没有发布代码,因为我已经在家里尝试过,但没有成功,不得不求助于 std::shared_ptr。我的问题是是否有人知道如何仅使用 std::unique_ptr 来实现双向链表。我只能创建一个“半名单”解决方案,因为我发现移动机制不足。有没有办法做到这一点?提供部分唯一性的好答案。 查看我回答的第一部分。我放了一段来澄清为什么不可能有unique_ptr
-only-list。
那么这就是我寻求的答案。我感谢你提供它。如果其他人认为他们可以仅使用 std::unique_ptr 实现双向链表,请随时发布解决方案。
如果要添加虚拟节点怎么办?我们在最后一个节点和头部的虚拟节点上有 unique_ptr - 看起来不太好。
@Gusev Slava 你想在哪里添加虚拟节点?你能提供一些显示问题的代码吗?【参考方案2】:
这是我使用的,
https://gist.github.com/mukunda-/153d802065c130e2956c
当然是使用“半唯一”方法,因为这是唯一可能的方法。
它的作用是控制分配给它的 unique_ptr,并且与列表中的项目的任何交互都使用普通指针完成。如果您从列表中拉出一个项目,那么您将获得所有权。
本质上,它为您提供了使用智能指针自动删除的便利。当然,如果您在处理其中一个对象时删除列表对象,它会中断,在这种情况下,您需要一个 shared_ptr 列表。
【讨论】:
【参考方案3】:是的,它可以通过使用任何指针(下一个或上一个)作为 unique_ptr 和另一个作为原始指针来完成。 请参阅 CppCon 2016:Herb Sutter “C++ 中的无泄漏……默认情况下”。 CppCon 2016: Herb Sutter “Leak-Freedom in C++... By Default.”
【讨论】:
以上是关于使用 std::unique_ptr 的双向链表的主要内容,如果未能解决你的问题,请参考以下文章