[英]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
};
基類已派生到Derived1
和Derived2
。 前者返回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.