Bad practice for returning unique_ptr for a raw pointer like property semantics?

I wrote a static factory method that returns a new Foobar object populated with another data object. I was recently obsessed with semantics of ownership and am wondering if I am passing the correct message if this factory method returns unique_ptr .

 class Foobar { public: static unique_ptr<Foobar> factory(DataObject data); } 

My intention is to tell the client code that they have a pointer. Without a smart pointer, I would simply return Foobar* . However, I would like to ensure that this memory is deleted in order to avoid possible errors, so unique_ptr seemed like a good solution. If the client wants to extend the pointer's lifetime, it simply calls .release() after receiving unique_ptr .

 Foobar* myFoo = Foobar::factory(data).release(); 

My question has two parts:

  • Is this approach appropriate to the proper semantics of ownership?
  • Is it a "bad practice" to return unique_ptr instead of a raw pointer?
+46
c ++ smart-pointers unique-ptr ownership-semantics
Jan 03 2018-12-12T00:
source share
3 answers

Returning std::unique_ptr from the factory method is great and should be a recommended practice. The message it sends (IMO): Now you are the sole owner of this object. In addition, for your convenience, the object knows how to destroy itself.

I think this is much better than returning a raw pointer (where the client must remember how and if to delete this pointer).

However, I do not understand your comment about releasing the pointer in order to extend its life. In general, I rarely see any reason for calling release on smartpointer, since I believe that pointers should always be controlled by some kind of RAII structure (about the only situation when I call release ) is to put the pointer in another controlling data structure e.g. a unique_ptr with another deleter, after I did something to guarantee extra cleanup).

Therefore, the client can (and should) simply store unique_ptr somewhere (for example, another unique_ptr that was moved, built from the returned one) if they need an object (or shared_ptr if they need several copies of the pointer). Thus, the clientside code should look like this:

 std::unique_ptr<FooBar> myFoo = Foobar::factory(data); //or: std::shared_ptr<FooBar> myFoo = Foobar::factory(data); 

Personally, I would also add a typedef for the return type of the pointer (in this case std::unique_ptr<Foobar> ) and the used deleter (in this case std :: default_deleter) for your factory object. This will simplify if you later decide to change the selection of your pointer (and therefore, you must use another method to destroy the pointer, which will be displayed as the second parameter of the std::unique_ptr ). So I would do something like this:

 class Foobar { public: typedef std::default_deleter<Foobar> deleter; typedef std::unique_ptr<Foobar, deleter> unique_ptr; static unique_ptr factory(DataObject data); } Foobar::unique_ptr myFoo = Foobar::factory(data); //or: std::shared_ptr<Foobar> myFoo = Foobar::factory(data); 
+57
Jan 03 '12 at 22:00
source share

A std::unique_ptr uniquely owns the object it points to. It says: "I own this object, and no one else does."

This is exactly what you are trying to express: you say "calling this function: you are now the sole owner of this object, do with it as you please, your life is your responsibility."

+17
Jan 03 2018-12-12T00:
source share

It accurately conveys the correct semantics, and so I think that all C ++ factories should work: std::unique_ptr<T> does not impose any property semantics and it is very cheap.

+6
Jan 03 2018-12-12T00:
source share



All Articles