2017-05-08 101 views
5

我的做法是:如何将所有权从原始指针正确移动到std :: unique_ptr?

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

上午我在做正确的一切还是有什么更好的办法呢?

+0

你不需要'std :: move'。 – juanchopanza

+0

在基元类型(指针)上调用'std :: move'没有意义。 –

回答

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兼容)。

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

+0

谢谢。但我更感兴趣的是[CppCoreGuidelines R.33](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#r33-take-a-unique_ptrwidget-parameter-to-express-that-a -function-reseats-thewidget)。我需要把ref作为myObject,因为我不想在函数返回后将它删除。另外VS2013表示,如果我尝试通过val传递它,该函数将被删除。或者我错了? – Oliort

+0

@Oliort函数返回后,它不会被删除,因为您将std :: move()放入vector的'std :: unique_ptr'中。在std :: move之后,参数版本成为'nullptr' – Galik

相关问题