【问题标题】:How to store references to other objects in C++?如何在 C++ 中存储对其他对象的引用?
【发布时间】:2021-09-16 11:04:00
【问题描述】:

这是一个更普遍的问题,我正在尝试解决 C++ 最佳实践。假设我想创建存储相互引用的对象,例如图形。所有对象都属于同一个对象,就像一个Graph对象属于所有Node,也就是说所有权是固定的。

这是我的想法:一个类 Graph 有一个 std::vector 的节点,每个节点都有一个 std::vector 的节点代表它的连接列表。我想知道如何最好地在智能指针方面实现这一点?据我了解,所有权是唯一的,因此 Graph 向量应该是 std::vector<std::unique_ptr<Node>> nodes,我可以根据需要填充它。但是connections 向量,如何让每个节点存储对其连接的引用?这些只是只读引用,也许最好命名所有节点并仅存储名称,或者将连接存储在 Graph 中。但是有没有一种很好的方法来存储对连接节点的引用,就好像它们是 const 指针一样?

注意:这实际上是关于所有权和智能指针,而不是数据结构,图示例只是一个示例。

【问题讨论】:

  • 有趣的是,一张图表是围绕 Herb Sutter 的 gcpp 项目与 deferred_ptrs 的激励性讨论。也就是说:这是一个有点宽泛且可能基于意见的问题,因为它可以通过多种方式解决;在图中具有强 unique_ptr 的节点上的原始指针查看,或节点中的 weak_ptrGraph 中的 shared_ptrs,或者像 deferred_ptrs 这样更奇特的东西。没有什么本质上是“正确的”或“错误的”——这取决于用例和所需的质量属性
  • @Human-Compiler 我明白你的观点是基于意见的,所以也许我可以改变问题来询问特定方法,答案可能会批评并提供替代方案?
  • 您已经对所提出的问题有了答案——我会犹豫是否要以可能使现有答案无效的方式更改它(这会使回答者感到不安)。无论哪种方式,这都不是一个坏问题

标签: c++ reference smart-pointers move-semantics


【解决方案1】:

在讨论“最佳实践”时,重要的是要考虑代码的质量属性和需求。

Graph 等代码示例中没有“正确”或“错误”的答案;有不同程度以不同的方式解决不同的问题——这很大程度上取决于它的预期使用方式。

到目前为止,解决此类问题的最简单方法是让主容器 (Graph) 在unique_ptr 中拥有强所有权,并且只查看使用原始指针的内部元素 (Node) 中的生命周期,例如:

class Graph
{
    ...
private:
    std::vector<std::unique_ptr<Node>> m_nodes;
};

class Node
{
    ...
private:
    std::vector<const Node*> m_connected_nodes;
};

这会很好用,因为Node 不能改变其连接的节点,并且因为Graph 假设Node 永远不会超过它。

然而,如果您希望NodeGraph 寿命更长,或者如果您希望Node 用于多个@,这种方法不起作用 987654332@ 对象。如果它位于不同的Graphs 之间,那么您可能会冒Node 引用悬空指针的风险——这很糟糕。

如果是这种情况,您可能需要考虑不同的所有权模式,例如 shared_ptrweak_ptr 所有权:


class Graph
{
    ...
private:
    std::vector<std::shared_ptr<Node>> m_nodes;
};

class Node
{
    ...
private:
    std::vector<std::weak_ptr<const Node*>> m_connected_nodes;
};

在这种情况下,Nodes 仅微弱地知道其他 Node 对象,而 Graph 是它们的强所有者。这可以防止悬空问题,但现在会为shared_ptr 的控制节点带来额外的开销,并且必须在访问weak_ptr 节点之前检查它是否处于活动状态。

所以正确答案是:视情况而定。如果您可以摆脱前一种方法,那可能是最干净的;您总是有 1 个所有者,因此逻辑简单易懂。

【讨论】:

    【解决方案2】:

    我想知道如何在智能指针方面最好地实现这一点?

    不使用它们。为图形使用节点向量:std::vector&lt;Node&gt;。这是一个合理的默认选择,除非您有充分的理由不这样做。

    但是有没有一种好的方法来存储对连接节点的引用,就好像它们是 const 指针一样?

    是的。 const 指针是一种很好的存储方式,就好像它们是 const 指针一样。 (通过“const 指针”,我认为我们实际上是在谈论指向 const 的指针)。

    引用包装器是另一种选择。虽然它的优点是没有 null 的表示,但它确实有语法笨拙的缺点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-21
      • 1970-01-01
      • 1970-01-01
      • 2016-05-04
      • 2013-01-24
      • 2014-02-16
      • 1970-01-01
      相关资源
      最近更新 更多