繁体   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