[英]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.