簡體   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