How to correctly transfer ownership from an raw pointer to std :: unique_ptr?

My approach:

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

Am I doing everything right or are there better solutions?

+5
source share
2 answers

move is redundant.

I would do this:

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

because I would like to move the unique_ptr semantics as unique_ptr as possible.

I can write this utility function:

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

so that callers can:

 foo.takeOwnership(wrap_in_unique(some_ptr)); 

but even better, then you can infer the boundaries of the unique_ptr semantics as much as possible.

I could even do:

 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); } 

which allows callers to easily switch to T* in unique_ptr . All of their T*unique_ptr<T> now wrapped in std::move and the zeros of the source pointer.

So if they had

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

code can be converted to:

 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)) ); } }; 

and it still compiles and works the same way. (Other interactions with I_own_this may change, but part of it will already be I_own_this compatible).

+4
source

You must accept unique_ptr from get-go:

 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)); } }; 

In this way, you make it clear that you are taking responsibility and also help other programmers avoid using raw pointers.

Additional Information: CppCoreGuidelines R.32

+2
source

All Articles