【问题标题】:Proper way of transferring ownership of a std::vector< std::unique_ptr< int> > to a class being constructed将 std::vector< std::unique_ptr< int> > 所有权转移到正在构造的类的正确方法
【发布时间】:2013-08-19 09:14:08
【问题描述】:

std::vector&lt;unique_ptr&lt;int&gt; &gt; 的所有权转移到正在构建的类的正确方法是什么?

下面是我想要做的代码表示。我意识到无论是通过值还是通过引用将向量传递给构造函数,它都是不正确的(不会编译)并且违反了“唯一性”。我希望 Foo 成为向量的新所有者,并希望调用函数放弃所有权。我需要构造函数获取std::unique_ptr&lt;std::vector&lt;std::unique_ptr&lt;int&gt; &gt; &gt; 来执行此操作吗?

Foo.h

class Foo
{
public:
  Foo(vector<std::unique_ptr<int> > vecOfIntPtrsOwnedByCaller);

private:
  vector<std::unique_ptr<int> > _vecOfIntPtrsOwnedByFoo;
}

Foo.cpp

Foo::Foo(std::vector<std::unique_ptr< int> > vecOfIntPtrsOwnedByCaller)
{
    _vecOfIntPtrsOwnedByFoo = vecOfIntPtrsOwnedByCaller;
}

任何帮助将不胜感激 - 我已经在网上搜寻了正确的方法来做到这一点。谢谢!

【问题讨论】:

  • std::vector&lt;std::unique_ptr&lt;int&gt;&gt; 需要一个临时的,或者调用者在他们自己的向量上使用std::move,因为它不能被复制进去。如果你想让它变得非常明确,考虑@ 987654327@。之后,使用std::move 进入您的成员(在成员初始化程序中!)。
  • 您希望向量是唯一拥有的,还是其中包含的元素?
  • 轨道上的亮度竞赛 - 两者兼而有之。
  • Xeo - 感谢您的回复。我现在只是在阅读右值引用。如果我理解正确,构造函数应该对向量进行右值引用并执行 _vecOfIntPtrsOwnedByFoo(std::move(vecOfIntPtrsRvalRefence))。我不完全清楚如何使传递给构造函数的向量成为临时/右值。我试图传递给构造函数的向量是另一个类的全局变量。

标签: c++ c++11 stdvector unique-ptr ownership


【解决方案1】:

std::unique_ptr&lt;T&gt; 是不可复制但可移动的类型。在 std:vector&lt;T&gt; 中具有仅移动类型也使 std::vector&lt;T&gt; 仅移动。要让编译器自动移动对象,您需要有一个用于移动构造或移动赋值的 r 值。在您的构造函数中,对象vecOfIntPtrsOwnedByCaller 是一个左值,尽管它的名称已经拥有指向ints 的对象:当调用者创建对象时,它们从调用者那里“窃取”了。要从左值移动,您需要使用std::move()(或等效的东西):

Foo::Foo(std::vector<std::unique_ptr<int>> vecOfIntPtrsOwnedByCaller)
{
    _vecOfIntPtrsOwnedByFoo = std::move(vecOfIntPtrsOwnedByCaller);
}

或者,最好的

Foo::Foo(std::vector<std::unique_ptr<int>> vecOfIntPtrsOwnedByCaller)
    : _vecOfIntPtrsOwnedByFoo(std::move(vecOfIntPtrsOwnedByCaller))
{
}

后一种方法避免首先默认构造成员,然后移动分配给它,而是直接移动构造成员。我想,我也会将参数设为 r 值引用,但这不是必需的。

请注意,您只能从可以绑定到 r 值的对象构造 Foo 类型的对象,例如:

int main() {
    Foo f0(std::vector<std::unique_ptr<int>>()); // OK
    std::vector<std::unique_ptr<int>> v;
    Foo f1(v); v// ERROR: using with an l-value
    Foo f2{v}; v// ERROR: using with an l-value
    Foo f3 = v; // ERROR: using with an l-value
    Foo f4(std::move(v)); // OK: pretend that v is an r-value
}

【讨论】:

  • 参考和交换的解决方案是否有效?我的意思是Foo(vector&lt;unique_ptr&lt;int&gt;&gt;&amp; v) { this-&gt;v.swap(v); }。坦率地说,我知道您的回答是正确且更好的 - 但使用 swap 也可能是 OP 要求“转让所有权”的一种方式?
  • @PiotrNycz:使用std::vector&lt;...&gt;swap() 也可以,但在成员初始化列表中使用std::move() 是传输内容的惯用方式。
  • 谢谢 Dietmar,您介意展示一个构造函数的示例,该构造函数也采用右值引用以及如何将向量传递给它吗?您如何决定使用哪个版本?
  • @Jen:只需在参数类型后添加&amp;&amp;。实现和使用都不会改变。
  • 好的!太感谢了!为什么我会选择一种方式而不是另一种方式?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-02-02
  • 1970-01-01
  • 2014-05-12
  • 2015-05-16
  • 2011-11-25
  • 2013-01-07
  • 2013-04-12
相关资源
最近更新 更多