簡體   English   中英

我們如何從成員函數返回unique_pointer成員?

[英]How do we return a unique_pointer member from a member function?

我有一個帶有指針成員的基類。 我必須做出有根據的猜測,以確定它應該是unique_ptr還是shared_ptr 他們似乎都沒有解決我的特定用例。

class Base
{
public:
    Base(): pInt(std::unique_ptr<int>(new int(10))) {};
    virtual std::unique_ptr<int> get() = 0;
    //Base(): pInt(std::shared_ptr<int>(new int(10))) {}; // Alternate implementation
    //virtual std::shared_ptr<int> get() = 0; // Alternate implementation
private:
    std::unique_ptr<int> pInt;
    //std::shared_ptr<int> pInt; // Alternate implementation
};

基類已派生到Derived1Derived2 前者返回unique_ptr成員pInt ,后者返回本地unique_ptr對象。

class Derived1: public Base
{
public:
    Derived1() {};
    virtual std::unique_ptr<int> get()
    {
        //return std::move(pInt);  Will compile but the ownership is lost
        return pInt;
    }
private:
    std::unique_ptr<int> pInt;
};
class Derived2: public Base
{
public:
    Derived2() {};
    virtual std::unique_ptr<int> get()
    {
        std::unique_ptr<int> pInt(new int());
        return pInt;
    }
private:
    std::unique_ptr<int> pInt;
};

Derived1的get實現不會隱式轉移所有權,因為成員指針變量不是eXpiring值,而Derived2的實現可以。 標准中詳細記錄了此行為

見12.8§34和§35:

當滿足某些條件時,允許實現省略類對象的復制/移動構造[...]復制/移動操作的省略,稱為復制省略,允許在...的返回語句中。具有類返回類型的函數,當表達式是非易失性自動對象的名稱時,具有與函數返回類型相同的cv-nonqualified類型[...]

當滿足復制操作的省略標准並且要通過左值指定要復制的對象時,首先執行用於選擇復制的構造函數的重載決策,就好像該對象由右值指定一樣。

然而,如果我通過std::move顯式轉移所有權,則成員指針將來將無法使用。

或者,我必須將指針的定義設置為shared_ptr但這將是Derived2::get實現的額外開銷。

注意應該考慮Derived2::get的出現與Derived1::get比較,因此使用std:: shared_ptr的設計決策會產生相當大的相對影響。

您的Derived1案例無法按照您想要的方式處理unique_ptr 您需要多個智能指針指向同一資源。 unique_ptr根本不是一個選項。 沒有辦法解決這個問題。

你可以堅持使用unique_ptr成員,但是讓你的函數返回一個原始指針。

virtual int *get() = 0;

這對於Derived2類來說很麻煩,因為不清楚調用者是否應該釋放指向的內存。 我建議你要這樣做。

您可以按照建議使用shared_ptr成員,並使您的函數返回該成員。 這在Derived2類中完全Derived2 ,但正如您所指出的那樣,次優。

不過,它仍然是最干凈的解決方案。 對於只知道他們有Base調用者,你需要一些方法來通知他們(手動或通過返回的類型)當他們完成get()的結果時他們應該做什么,所以你不能返回unique_ptr<int>無論如何unique_ptr<int>

返回unique_ptr<int>的函數唯一有用的方法是調用者已經知道你有Derived2 但是,您可以添加一個新成員:

virtual shared_ptr<int> get() {
  return get_unique();
}
virtual unique_ptr<int> get_unique() {
    std::unique_ptr<int> pInt(new int());
    return pInt;
}

我只會這樣做,如果分析顯示shared_ptr<int> get()成員實際上增加了可衡量的開銷。 您的shared_ptr<int>實現很有可能在性能方面是充分的,然后可讀性應該是添加新成員的原因。

unique_ptr的目的是指向來自唯一位置的資源。 如果您需要從多個位置指向此資源,則unique_ptr不再適用。 在這種情況下,您應該使用shared_ptr。
如果釋放資源的所有權適合您的邏輯,那么只需使用:

unique_ptr<int> get()
{
   return move(pInt);// this will move the ownership of the resource away from the member field
}

......但從現在開始,pInt已不再有效。

如果你小心資源(如果你不擔心懸空指針),那么只需返回指向資源的原始指針(但請不要使用shared_ptr)。

在使用shared_ptr的情況下,要小心循環依賴,使用weak_ptr做反計數。 以下是它的內容: http//geekwentfreak-raviteja.rhcloud.com/blog/2014/07/06/c11-how-to-create-cyclic-dependencies-with-shared_ptr-and-how-to-avoid-他們/?_ sm_au_ = irVM6PVF1TR4nGMW

編輯后:當您使用unique_ptr作為成員字段時,您將丟失復制構造函數,因為無法復制unique_ptr。 FYI

但是,在我看來,使用unique_ptr作為額外的開銷,只需直接使用shared_ptr或int。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM