簡體   English   中英

unique_ptr所有權語義

[英]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中被TestFooMockDep* 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> ,但我更願意能夠執行后者,因為它明確記錄了所有權語義。

什么是最合適(或失敗,不引人注目)的解決方法?

編輯FooOtherObject都是我正在定義的構造函數的類。

你可以使用:

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_;
};

第三個解決方案是改變之間的順序OtherObjectchild_ (具有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.

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