Your analysis is quite correct, I think. In this situation, I also would return a bare B*
, or even a [const] B&
if the object is guaranteed to never be null.
Having had some time to peruse smart pointers, I arrived at some guidelines which tell me what to do in many cases:
- If you return an object whose lifetime is to be managed by the caller, return
std::unique_ptr
. The caller can assign it to astd::shared_ptr
if it wants. - Returning
std::shared_ptr
is actually quite rare, and when it makes sense, it is generally obvious: you indicate to the caller that it will prolong the lifetime of the pointed-to object beyond the lifetime of the object which was originally maintaining the resource. Returning shared pointers from factories is no exception: you must do this eg. when you usestd::enable_shared_from_this
. - You very rarely need
std::weak_ptr
, except when you want to make sense of thelock
method. This has some uses, but they are rare. In your example, if the lifetime of theA
object was not deterministic from the caller’s point of view, this would have been something to consider. - If you return a reference to an existing object whose lifetime the caller cannot control, then return a bare pointer or a reference. By doing so, you tell the caller that an object exists and that she doesn’t have to take care of its lifetime. You should return a reference if you don’t make use of the
nullptr
value.