class B; class A { public: A () : m_b(new B()) { } shared_ptr<B> GimmeB () { return m_b; } private: shared_ptr<B> m_b; };
Let's say B is a class that semantically should not exist outside of the lifetime of A, i.e., it makes absolutely no sense for B to exist by itself. Should GimmeB
return a shared_ptr<B>
or a B*
?
In general, is it good practice to completely avoid using raw pointers in C++ code, in lieu of smart pointers?
I am of the opinion that shared_ptr
should only be used when there is explicit transfer or sharing of ownership, which I think is quite rare outside of cases where a function allocates some memory, populates it with some data, and returns it, and there is understanding between the caller and the callee that the former is now "responsible" for that data.
An object referenced by the contained raw pointer will not be destroyed until reference count is greater than zero i.e. until all copies of shared_ptr have been deleted. So, we should use shared_ptr when we want to assign one raw pointer to multiple owners. // referring to the same managed object.
Pointers (along with references) are used extensively in C++ to pass larger objects to and from functions. It's often more efficient to copy an object's address than to copy the entire object. When defining a function, specify pointer parameters as const unless you intend the function to modify the object.
In short: Use unique_ptr when you want a single pointer to an object that will be reclaimed when that single pointer is destroyed. Use shared_ptr when you want multiple pointers to the same resource.
The rule would be this - if you know that an entity must take a certain kind of ownership of the object, always use smart pointers - the one that gives you the kind of ownership you need. If there is no notion of ownership, never use smart pointers.
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:
std::unique_ptr
. The caller can assign it to a std::shared_ptr
if it wants.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 use std::enable_shared_from_this
.std::weak_ptr
, except when you want to make sense of the lock
method. This has some uses, but they are rare. In your example, if the lifetime of the A
object was not deterministic from the caller's point of view, this would have been something to consider.nullptr
value.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With