[英]unique_ptr ownership semantics
也許我試圖過於通用。 (下面的原始問題)具體來說,我有一個類Foo
依賴Dep
。 我還有一個類MockDep
,我正在定義一個類TestFoo
。 這是我試圖寫的構造函數:
TestFoo(unique_ptr<MockDep> dep) : Foo(std::move(dep)), mock_dep_(dep.get()) {}
而Foo
的構造函數看起來像:
Foo(unique_ptr<Dep> dep) : dep_(dep) {}
mock_dep_
在TestFoo中被TestFoo
為MockDep* mock_dep_
,而dep_
在Foo
被聲明為unique_ptr<Dep> dep_
。 如何讓mock_dep_
包含dep_
的地址? (如上述,因為不工作std::move(dep)
空值了dep
)。
原帖:
我有一個類型為Foo
的對象,我要傳遞給另一個類型為OtherObject
對象,它聲明對它的所有權,但作為指向其基類的指針。 但是,我想抓住一個指向我可以用來引用它的子對象的指針。 我寫了類似的東西:
Foo(std::unique_ptr<Child> thing) :
OtherObject(std::move(thing)), child_(thing.get()) {}
OtherObject(std::unique_ptr<Base> thing, ...) { ... }
但是,這似乎不起作用,因為std::move(thing)
似乎將稍后從thing.get()
返回的指針置空。
我可以將Foo
的參數更改為Child*
類型而不是unique_ptr<Child>
,但我更願意能夠執行后者,因為它明確記錄了所有權語義。
什么是最合適(或失敗,不引人注目)的解決方法?
編輯 : Foo
和OtherObject
都是我正在定義的構造函數的類。
你可以使用:
Foo(std::unique_ptr<Child> thing) :
OtherObject(std::move(thing)),
child_(OtherObject.getChildPtr()) /* one accessor to get the pointer. */
{}
如果基礎對象OtherObject
不提供指針的訪問器,則可以將構造函數委托給其他構造函數,例如:
class Foo: public OtherObject
{
public:
Foo(std::unique_ptr<Child> thing) : Foo(thing, thing.get()) {}
private:
Foo(std::unique_ptr<Child>& thing, Child* child) :
OtherObject(std::move(thing)),
child_(child)
{}
private:
Child* child_;
};
第三個解決方案是改變之間的順序OtherObject
和child_
(具有child_
通過引入其它推導前):
class ChildPtr
{
public:
ChildPtr(Child* child) : child_(child) {}
Child* child_;
};
class Foo: private ChildPtr, public OtherObject
{
public:
Foo(std::unique_ptr<Child> thing) :
ChildPtr(thing.get()),
OtherObject(std::move(thing))
{}
};
通常情況會在標准中描述為:
§17.6.5.15.1 從庫類型的狀態移出[lib.types.movedfrom]
可以從(12.8)移動C ++標准庫中定義的類型的對象。 可以顯式指定或隱式生成移動操作。 除非另有規定,否則此類移動對象應置於有效但未指定的狀態。
該標准實際上具體描述了std::unique_ptr
的行為:
§20.8.1.4 類模板unique_ptr [unique.ptr]
此外,
u
可以根據要求,將所有權轉讓給另一種獨特的指針u2
。 完成此類轉移后,以下后置條件成立:
- u2.p等於轉移前,
- up等於nullptr,和
- 如果預轉移ud維持狀態,則此類狀態已轉移到u2.d.
具體來說,在構建Foo
子對象之后, dep
:
Foo(std::move(dep))
是一個nullptr
。
此外,如果dep
仍然是一個有效的指針, Foo(std::move(dep))
將復制dep
,這對std::unique_ptr
的語義沒有意義(因為它是不可復制的)。
你想要做的是在Foo
引用指向對象,並適當考慮大小寫(例如,unique_ptr可以為nullpt
?等等)。
class Foo {
public:
Foo(unique_ptr<Dep> dep) : dep_(dep) {}
const Dep& get_dep() const { return *dep_; }
Dep& get_dep() { return *dep_; }
private:
std::unique_ptr<Dep> dep_;
};
然后簡單地構造TestFoo
對象:
TestFoo(unique_ptr<MockDep> dep) : Foo(std::move(dep)) {}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.