如何给 child 一个指向 parent 的弱指针? (C++)

How to give a child a weak pointer to a parent? (C++)

我读过 here,在某些 parent object 唯一拥有几个 children 的情况下,每个 child 需要能够访问它的 parent,应该使用弱指针作为 back-pointer 而不是共享指针,以避免依赖循环。

我有两个问题:

  1. 与简单引用相比,给 parent 一个弱指针有什么好处?
  2. 在下面的代码中,我应该如何向每个 child 传递一个指向其 parent 的弱指针?我知道您可以从 std::enable_shared_from_this 继承以从 this 获取共享指针。有弱指针的等价物吗?或者别的什么?
#include <memory>
#include <vector>

class Parent;

class Child {
 public:
  void set_parent(std::weak_ptr<Parent> parent) {
    parent_ = parent;
  }
  std::weak_ptr<Parent> parent_;
};

class Parent {
  void add_child(std::unique_ptr<Child> child) {
    // child->set_parent(???);
    children_.push_back(std::move(child));
  }
  std::vector<std::unique_ptr<Child>> children_;
};

weak_ptrs 来自 shared_ptrs。如果您的 parent 节点“唯一拥有”children,那么 children cannotweak_ptrs 到他们的 parents,因为这需要它们的 shared_ptr 存在于某处。

请注意,您引用的示例并未说明项目之间关系的“唯一所有权”。

此外,只要 parents 永远不会放弃 children 的所有权给系统外的代码,就没有理由不只是有一个指向 [=23] 的常规指针=](它需要是一个指针,因为不能更改引用)。指针将始终有效(从系统外部),因为 parent 必须存在才能使 child 存在。毕竟,这就是独特所有权的含义。

你说过 parent 总是唯一拥有一个 child 但你没有指定一些东西:

  1. 复制一个childobject有效吗?
  2. 移动一个childobject有效吗?

如果您对其中任何一个的回答是肯定的,那么您必须考虑如果 child 在 parent 之间复制或移动会发生什么,因为您的 child class 不会默认情况下阻止它。所以我的建议是显式删除复制和移动构造函数和赋值运算符,或者如果你想要这种能力,那么你有责任确保如果 child 被复制和/或移动它的 parent 指针指向正确的 parent 并防止它指向无效/删除的 parent.

如果你沿着显式禁用复制和移动语义的路线走下去,那么在那种情况下我想不出有什么会阻止你使用对 parent 的引用相反。

最后,如果您确实希望 children 中的弱指针指向它们的 parent,那么您可以考虑让 parent class 扩展自:enable_shared_from_this。我认为典型的用例是当你不知道你是否会比另一个 object 长寿但在它仍然有效的情况下 object 然后你想确保它在你的时候保持活力对其进行一些操作。

请注意,如果您采用这种方法,parent object 必须存储在 shared_ptr 中。参见 shared_from_this。如果不是,那么您处于未定义的行为领域,让所有人都同意这是不好的。

编辑:我忘了说如果你可以使用 C++17,你可以直接从 parent 得到 weak_ptr 传递给 child:weak_from_this