如何正确地将所有权从裸指针转移到std::unique_ptr?

8

我的方法是:

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

我是否正在正确地执行所有操作?或者是否存在更好的解决方案?


你不需要使用 std::move - juanchopanza
在原始类型(指针)上调用std::move没有意义。 - M.M
2个回答

4

你应该从一开始就接受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

4

move是多余的。

我会这样做:

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

因为我希望尽可能将unique_ptr的所有权语义“向外”移动。我可能会编写此实用程序函数:
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*->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兼容的)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接