【问题标题】:Using smart pointers in Doubly Linked Lists在双向链表中使用智能指针
【发布时间】:2019-02-08 00:55:43
【问题描述】:

以下是我对智能指针的了解

  1. shared_ptr 是一个智能指针,因此多个 shared_ptr 可以指向堆中的一个对象。即使其中一个 shared_ptr 被删除,只要它的引用计数高于零,堆中的对象也不会被销毁。
  2. weak_ptr 也指向堆中的一个对象,但它不会增加该对象的引用计数
  3. 我们可以使用weak_ptr来打破循环引用

在双向链表的情况下,我们有两个指针指向上一个节点和下一个节点。我们在实现中使用了 shared_ptr 和 weak_ptr。我们为什么不使用两个 weak_ptr 呢?

【问题讨论】:

  • 我们为什么不直接使用std::list?
  • 说真的,我建议不要在实现低级数据结构时使用智能指针。
  • "我们可以使用weak_ptr 来打破循环引用" 算了。这是“解释”它的最糟糕的方式。

标签: c++ pointers c++14 smart-pointers weak-ptr


【解决方案1】:

我们不使用两个weak_ptr,因为它不起作用。

想象一个有两个节点的列表。列表头是第一个节点的非弱 ptr。所以第一个节点保持活动状态。但是什么非弱指针使第二个节点保持活动状态?

管理对象的生命周期有两个挑战。他们应该活得足够长,但不能太久。这不仅适用于 C++ 或智能指针,这几乎是所有编程语言中的一个基本问题。您可以通过了解您正在处理的问题并用您的语言为您提供的工具表达该问题来解决它。

【讨论】:

  • 我明白了。假设我们有一个包含 10 个元素的双向链表,使得前一个和下一个指针都是weak_ptr。如果某个其他指针指向第 5 个节点并且该指针被删除。它指向的节点也被破坏了,因此,我们将无法访问第 5 个元素之后的元素。但是,如果我们使用 shared_ptr,那么第 5 个节点将受到保护而不会被破坏。这是你想说的吗?
  • @GaurangaDas:前提是有缺陷的。由于我们没有保持其他元素活动的指针,因此列表不会有 10 个元素开始。我们有两个不构成列表的元素(第一个和“第五个”)。
【解决方案2】:

我们可以使用shared_ptrnextweak_ptrprev,但不能使用两个weak_ptr。如果没有指向节点的shared_ptr,则引用计数变为零,weak_ptr 变为nullptr

无论如何,将shared_ptr 用于链接列表是一种过度杀伤力。由于只有一个对象拥有该节点(头节点或前一个节点),一个简单的unique_ptr 用于next 就可以了,带有一个指向prev 的原始指针。

请注意,使用链表使用智能指针是有风险的。当一个长列表被破坏时,问题就出现了,它被递归地破坏了。节点析构函数调用智能指针的析构函数,智能指针的析构函数调用节点析构函数。 stacj 很可能会在 O(n) 中增长。由于列表可能比可能的最大堆栈长,代码可能用完堆栈空间并崩溃

这并不意味着不能使用智能指针,只是节点必须实现析构函数。析构函数必须在循环中擦除节点,这样就不会调用递归。

【讨论】:

  • 对于一个weak_ptr指向一个对象,对象的引用计数是否必须大于零?
  • @GaurangaDas 是的,如果引用计数为零,则对象被销毁,weak_ptr 指向 null。
猜你喜欢
  • 1970-01-01
  • 2016-08-08
  • 1970-01-01
  • 2020-12-20
  • 2013-11-15
  • 2016-10-09
  • 2020-12-04
  • 2013-10-29
  • 1970-01-01
相关资源
最近更新 更多