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

Oli*_*ort 6 c++ smart-pointers

我的方法是:

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

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

Yak*_*ont 4

move是多余的。

我自己,我会这样做:

void takeOwnership(std::unique_ptr<MyObject> nowItsReallyMyObject)
{
    myObjects.emplace_back(std::move(nowItsReallyMyObject));
}
Run Code Online (Sandbox Code Playgroud)

因为我想将unique_ptr所有权语义尽可能地“移出”。

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

template<class T>
std::unique_ptr<T> wrap_in_unique( T* t ) {
  return std::unique_ptr<T>(t);
}
Run Code Online (Sandbox Code Playgroud)

因此呼叫者可以:

foo.takeOwnership(wrap_in_unique(some_ptr));
Run Code Online (Sandbox Code Playgroud)

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);
}
Run Code Online (Sandbox Code Playgroud)

这让呼叫者可以更轻松地转换T*unique_ptrs 。它们的所有T*->unique_ptr<T>现在都包装在 a 中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)) );
  }
};
Run Code Online (Sandbox Code Playgroud)

代码可以转化为:

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)) );
  }
};
Run Code Online (Sandbox Code Playgroud)

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