繁体   English   中英

返回 unique_ptr 私有成员数据而不转移所有权

[英]Returning unique_ptr private member data without transferring ownership

语境

下面的错误似乎告诉我,我无法从此 get 函数返回名为m_headunique_ptr 我只想返回我的unique_ptr m_head而不转移所有权。

自从引入智能指针以来,我一直在完全避免使用原始指针,因为原始指针不是异常安全的,存在内存管理开销和我已经意识到的其他问题。 也许在这样的情况下,我应该在小范围内简要使用它们?

在这方面,我认为我需要转移所有权,而不是我目前的方法。 我应该改为获取由unique_ptr管理的对象,创建一个新的shared_ptr来管理该对象,然后返回shared_ptr ,但需要一些确认。 我认为可能是这种情况,因为std::unique_ptr文档说:

unique_ptr 对象唯一地拥有它们的指针:没有其他设施应该负责删除该对象,因此没有其他托管指针应该指向它的托管对象,因为一旦他们不得不这样做,unique_ptr 对象就会删除他们的托管对象,而不考虑是否其他指针是否仍指向同一个对象,因此将指向该处的任何其他指针都保留为指向无效位置

错误

 `function "std::unique_ptr<_Ty, _Dx>::unique_ptr(const std::unique_ptr<_Ty, _Dx> &) 
 [with _Ty=mrobsmart::LinkedList::Node, _Dx=std::default_delete<mrobsmart::LinkedList::Node>]" 

 (declared at line 2337 of "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.15.26726\include\memory")

 cannot be referenced  -- it is a deleted function

代码

#include <memory>

class LinkedList
{
    private:
        std::unique_ptr<Node> m_head;

    public:
        LinkedList(int data) {
            m_head = std::make_unique<Node>(data);
        }

        const std::unique_ptr<Node> get_head() { return m_head; }
};

我只想返回我的 unique_ptr m_head 而不转移所有权。

那是不可能的。 unique_ptr是围绕每一步都转移其所有权的行为而设计的。

请注意,自从引入智能指针以来,我一直在完全避免使用原始指针,因为原始指针不是异常安全的,有内存管理开销和其他我知道的问题,但也许在某些情况下我应该使用它们简要地包含在一个小范围内?

原始指针并不邪恶。 将它们用作纯引用/间接引用是一个完全有效的用例——不涉及所有权、内存管理或异常安全。

当然,也可以返回 C++ 引用。 选择指针还是引用,取决于值是否可以为null,但归根结底也是代码风格的问题。

因此,其中任何一个(重要: const -qualify 函数):

    const Node* get_head() const { return m_head.get(); }
    const Node& get_head() const { return *m_head; }

“问题背后的问题”可能是您在不应该使用的情况下尝试使用unique_ptr 我同意应该避免使用原始指针,但是除了这两个之外还有其他选择。

std::unique_ptr的两个重要属性是:

  1. 表示未设置的值的能力(即null )。
  2. 转让所有权的能力。

如果您也不需要,最好将Node值直接存储在m_head中,即:

#include <memory>

class LinkedList
{
    private:
        Node m_head;

    public:
        LinkedList(int data) : m_head(data) {}

        const Node& get_head() { return m_head; }
};

如果代码示例是m_head可以“未设置”的真实场景的简化版本,我们将需要不同的解决方案。 std::optional将是一个选项。 就像std::unique_ptr一样, std::optional可以表示“未设置”,但与std::unique_ptr相比, std::optional不支持所有权转移。 如果您想防止所有权转让,使用一种使这种情况变得不可能的类型是向您的同事和您未来的自己传达您的意图的好方法。 代码将更改为:

#include <memory>

class LinkedList
{
    private:
        std::optional<Node> m_head;

    public:
        LinkedList(int data) : m_head(Node(data)) {}

        // some other code which can cause m_head to be empty

        const std::optional<Node> get_head() { return m_head; }
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM