也许我试图过于通用。 (下面的原始问题)具体来说,我有一个类Dep
的依赖Foo
。我还有一个班级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
中被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
和{{1}}都是我正在定义构造函数的类。
答案 0 :(得分:6)
您可以使用:
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))
{}
};
答案 1 :(得分:1)
通常情况会在标准中描述为:
§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等于转移前的u.p,
- u.p等于nullptr和
- 如果预转移u.d维持状态,则此状态已转移到u2.d。
具体来说,dep
,在构建Foo
子对象之后:
Foo(std::move(dep))
是nullptr
。
此外,如果dep
仍然是有效指针,则Foo(std::move(dep))
会复制dep
,这对std::unique_ptr
的语义没有意义(因为它不是-copyable)。
你要做的是在nullpt
中考虑到案例(例如,unique_ptr可以是Foo
?等等),引用指向的对象:
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)) {}