Returning a std::unique_ptr
from a factory method is just fine and should be a recommended practice. The message it conveys is (IMO): You are now the sole owner of this object. Furthermore, for your convenience, the object knows how to destroy itself.
I think this is much better then returning a raw pointer (where the client has to remember how and if to dispose of this pointer).
However I do not understand your comment about releasing the pointer to extend it's lifetime. In general I rarely see any reason to call release
on a smartpointer, since I think pointers should always be managed by some sort of RAII structure (just about the only situation where I call release
is to put the pointer in a different managing datastructure, e.g. a unique_ptr
with a different deleter, after I did something to warrant additional cleanup) .
Therefore the client can (and should) simply store the unique_ptr
somewhere (such as another unique_ptr
, which has been move constructed from the returned one) as long as they need the object (or a shared_ptr
, if they need multiple copies of the pointer). So the clientside code should look more 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 returned pointer type (in this case std::unique_ptr<Foobar>
) and or the used deleter (in this case std::default_deleter) to your factory object. That makes it easier if you later decide to change the allocation of your pointer(and therefore need a different method for destruction of the pointer, which will be visible as a second template parameter of 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);
Foobar
to transfers ownership. – Altonaltonarelease()
, the client code should keep the pointer as a smart pointer, converting it to ashared_ptr
if shared ownership is necessary or leaving it asunique_ptr
otherwise. – Alluvionrelease()
was out of context. I work on a fairly old project and I was trying to anticipate both the need and coworker concern about being able to handle a raw pointer out of the returnedunique_ptr
. – Phraseologyunique_ptr
, as the answers below confirm, seems to be an acceptable approach, and would allow for polymoprhism. – Phraseology