如何正确地将所有权从原始指针移动到std :: unique_ptr?

时间:2017-05-08 21:31:39

标签: c++ smart-pointers

我的方法是:

class SomeClass
{
    std::vector<std::unique_ptr<MyObject>> myObjects;
public:
    void takeOwnership(MyObject *nowItsReallyMyObject)
    {
        myObjects.emplace_back(std::move(nowItsReallyMyObject));
    }
};

我是在正确地做所有事情还是有更好的解决方案?

2 个答案:

答案 0 :(得分:4)

move是多余的。

我自己,我这样做:

void takeOwnership(std::unique_ptr<MyObject> nowItsReallyMyObject)
{
    myObjects.emplace_back(std::move(nowItsReallyMyObject));
}

因为我希望将unique_ptr所有权语义移到&#34; out&#34;尽可能。

我可能会写这个效用函数:

template<class T>
std::unique_ptr<T> wrap_in_unique( T* t ) {
  return std::unique_ptr<T>(t);
}

所以来电者可以:

foo.takeOwnership(wrap_in_unique(some_ptr));

但更好的是,可以将unique_ptr语义的边界推到合理的范围内。

我甚至可以这样做:

template<class T>
std::unique_ptr<T> wrap_in_unique( T*&& t ) {
  auto* tmp = t;
  t = 0;
  return std::unique_ptr<T>(tmp);
}
template<class T>
std::unique_ptr<T> wrap_in_unique( std::unique_ptr<T> t ) {
  return std::move(t);
}

可让来电者将T*转换为unique_ptr更容易。他们的所有T* - &gt; unique_ptr<T>现在都包含在std::move中,并将源指针归零。

所以,如果他们有

struct I_am_legacy {
  T* I_own_this = 0;
  void GiveMyStuffTo( SomeClass& sc ) {
    sc.takeOwnership( wrap_in_unique(std::move(I_own_this)) );
  }
};

代码可以转换为:

struct I_am_legacy {
  std::unique_ptr<T> I_own_this;
  void GiveMyStuffTo( SomeClass& sc ) {
    sc.takeOwnership( wrap_in_unique(std::move(I_own_this)) );
  }
};

它仍然编译和工作相同。 (与I_own_this的其他交互可能必须更改,但其中一部分已经与unique_ptr兼容)。

答案 1 :(得分:2)

您应该从一开始就接受unique_ptr

class SomeClass
{
    std::vector<std::unique_ptr<MyObject>> myObjects;
public:
    // tells the world you 0wNz this object
    void takeOwnership(std::unique_ptr<MyObject> myObject)
    {
        myObjects.push_back(std::move(myObject));
    }
};

通过这种方式,您可以清楚地了解自己的所有权,并且还可以帮助其他程序员避免使用原始指针。

进一步阅读:CppCoreGuidelines R.32