代码之家  ›  专栏  ›  技术社区  ›  Blindy

对返回std::unique_ptr感到困惑

  •  1
  • Blindy  · 技术社区  · 6 月前

    假设我有一个树结构,节点定义如下:

    struct Node
    {
        byte key_part;
        unique_ptr<Node> left, right, middle;
        TValue value;
    };
    unique_ptr<Node> root;
    

    这里的语义是正确的,我绝对不希望别人控制我的节点本身。它是我的树所独有的。

    但是,我想添加一个 内部的 辅助函数,用于基于内部语义搜索树并返回一个。。。什么?节点结构。这是一个私有函数,仅在内部用于插入节点并用外部数据填充、删除节点或返回 value 字段(不是节点本身)外部。该节点绝不会泄漏到外部。

    那么,我该如何编写函数呢?我回不去了 unique_ptr<Node> 从中,对吧?或者移动语义将发挥作用。我可以返回一个指针,但这似乎会破坏系统,而且还会导致别名问题。引用是相似的,但它阻止了我使用 nullptr 标记未找到结果。本质上,这样的返回类型是什么:

    /* return type here */ search(const span<byte>& key)
    {
        auto node = /* recursive search here, etc */;
        return /* what do I put here, given I have a unique_ptr<Node> reference? */;
    }
    
    1 回复  |  直到 6 月前
        1
  •  4
  •   Useless    6 月前

    但是,我想添加一个内部辅助函数,根据内部语义搜索树并返回一个。。。什么?

    只需返回一个原始指针。原始指针是非拥有null引用的规范表示,这正是您想要的。

    有关保证,请参阅 C++ Core Guidelines 关于这个问题。

    我可以返回一个指针,但这似乎会破坏系统,而且还会导致混叠问题。

    它不会破坏任何东西。

    当您有以下情况时,会出现别名问题:

    • 两个或多个指针(指向相同或指针可相互转换的类型)
    • 编译器必须假设它们可能重叠(即无法证明它们永远不会重叠)
    • 你写一个,读另一个
    • 因此,编译器必须假设写入操作可能改变了它应该读取的值,因此无法缓存读取的值
    • 但你知道指针真的永远不会重叠,并且更希望优化器缓存读取的内容

    典型的例子是 memcpy (假设范围不重叠)以及 memmove (必须采取额外的预防措施来处理可能重叠的范围)。

    无论你使用原始指针还是智能指针,都不会影响这一点。