What is a smart pointer and when should I use one?
C++ – What is a Smart Pointer and When to Use One
c++c++-faqc++11pointerssmart-pointers
Related Solutions
Shared ownership:
The shared_ptr
and weak_ptr
the standard adopted are pretty much the same as their Boost counterparts. Use them when you need to share a resource and don't know which one will be the last to be alive. Use weak_ptr
to observe the shared resource without influencing its lifetime, not to break cycles. Cycles with shared_ptr
shouldn't normally happen - two resources can't own each other.
Note that Boost additionally offers shared_array
, which might be a suitable alternative to shared_ptr<std::vector<T> const>
.
Next, Boost offers intrusive_ptr
, which are a lightweight solution if your resource offers reference-counted management already and you want to adopt it to the RAII principle. This one was not adopted by the standard.
Unique ownership:
Boost also has a scoped_ptr
, which is not copyable and for which you can not specify a deleter. std::unique_ptr
is boost::scoped_ptr
on steroids and should be your default choice when you need a smart pointer. It allows you to specify a deleter in its template arguments and is movable, unlike boost::scoped_ptr
. It is also fully usable in STL containers as long as you don't use operations that need copyable types (obviously).
Note again, that Boost has an array version: scoped_array
, which the standard unified by requiring std::unique_ptr<T[]>
partial specialization that will delete[]
the pointer instead of delete
ing it (with the default_delete
r). std::unique_ptr<T[]>
also offers operator[]
instead of operator*
and operator->
.
Note that std::auto_ptr
is still in the standard, but it is deprecated.
§D.10 [depr.auto.ptr]
The class template
auto_ptr
is deprecated. [ Note: The class templateunique_ptr
(20.7.1) provides a better solution. —end note ]
No ownership:
Use dumb pointers (raw pointers) or references for non-owning references to resources and when you know that the resource will outlive the referencing object / scope. Prefer references and use raw pointers when you need either nullability or resettability.
If you want a non-owning reference to a resource, but you don't know if the resource will outlive the object that references it, pack the resource in a shared_ptr
and use a weak_ptr
- you can test if the parent shared_ptr
is alive with lock
, which will return a shared_ptr
that is non-null if the resource still exists. If want to test whether the resource is dead, use expired
. The two may sound similar, but are very different in the face of concurrent execution, as expired
only guarantees its return value for that single statement. A seemingly innocent test like
if(!wptr.expired())
something_assuming_the_resource_is_still_alive();
is a potential race condition.
Always use a smart pointer wherever you own resources (memory, files etc). Owning them manually is extremely error prone and violates many good practices, like DRY.
Which one to use depends on what ownership semantics you need. unique_ptr
is best for single ownership, and shared_ptr
shared ownership.
As children do not own their parents, a raw parent pointer is fine. However, if the parents own their children, unique_ptr
works best here.
It's also notable that what on earth, a linked list of pointers? That makes no sense. Why not a linked list of values?
Best Answer
UPDATE
This answer is rather old, and so describes what was 'good' at the time, which was smart pointers provided by the Boost library. Since C++11, the standard library has provided sufficient smart pointers types, and so you should favour the use of
std::unique_ptr
,std::shared_ptr
andstd::weak_ptr
.There was also
std::auto_ptr
. It was very much like a scoped pointer, except that it also had the "special" dangerous ability to be copied — which also unexpectedly transfers ownership.It was deprecated in C++11 and removed in C++17, so you shouldn't use it.
OLD ANSWER
A smart pointer is a class that wraps a 'raw' (or 'bare') C++ pointer, to manage the lifetime of the object being pointed to. There is no single smart pointer type, but all of them try to abstract a raw pointer in a practical way.
Smart pointers should be preferred over raw pointers. If you feel you need to use pointers (first consider if you really do), you would normally want to use a smart pointer as this can alleviate many of the problems with raw pointers, mainly forgetting to delete the object and leaking memory.
With raw pointers, the programmer has to explicitly destroy the object when it is no longer useful.
A smart pointer by comparison defines a policy as to when the object is destroyed. You still have to create the object, but you no longer have to worry about destroying it.
The simplest policy in use involves the scope of the smart pointer wrapper object, such as implemented by
boost::scoped_ptr
orstd::unique_ptr
.Note that
std::unique_ptr
instances cannot be copied. This prevents the pointer from being deleted multiple times (incorrectly). You can, however, pass references to it around to other functions you call.std::unique_ptr
s are useful when you want to tie the lifetime of the object to a particular block of code, or if you embedded it as member data inside another object, the lifetime of that other object. The object exists until the containing block of code is exited, or until the containing object is itself destroyed.A more complex smart pointer policy involves reference counting the pointer. This does allow the pointer to be copied. When the last "reference" to the object is destroyed, the object is deleted. This policy is implemented by
boost::shared_ptr
andstd::shared_ptr
.Reference counted pointers are very useful when the lifetime of your object is much more complicated, and is not tied directly to a particular section of code or to another object.
There is one drawback to reference counted pointers — the possibility of creating a dangling reference:
Another possibility is creating circular references:
To work around this problem, both Boost and C++11 have defined a
weak_ptr
to define a weak (uncounted) reference to ashared_ptr
.