Reputation: 1678
I know, that std::shared_ptr
uses reference counting, so it has copy&move semantics, on the other hand std::unique_ptr
(hence the name unique) only has move semantics, so trying to copy it is a compile error.
However, its not quite clear for me how big of a deal is that. Can I simply use std::shared_ptr
over std::unique_ptr
in most cases, or should I use std::unique_ptr
whenever possible, as it's far more efficient because it doesn't have to take care of reference counting?
Also, I know that smart pointers are useful when dealing with, for example exception safety, but are they a mean to generally replace traditional T*
pointers?
Is it a good programming practice to use smart pointers over traditional T*
pointers whenever possible?
Upvotes: 3
Views: 2541
Reputation: 20790
You should prefer values to std::unique_ptr
, and std::unique_ptr
to std::shared_ptr
whenever possible, but not for performance reasons. Yes, there is some overhead when it comes to std::shared_ptr
, as they use inside some form of atomic counter, but this is negligible for most applications.
The main reason to use std::unique_ptr
is the uniqueness semantics - when you (or someone else) read(s) the code it's very clear the lifetime and the ownership of the object. This makes it more easy to reason about the code and find logical/performance issues.
PS: std::unique_ptr
has no overhead compared to raw pointer, but it has some great advantages.
Upvotes: 1
Reputation: 275730
shared_ptr
means that the ownership rules surrounding the resource are complicated. Understanding them requires tracking down the lifetime of all shared_ptr
s in the general case.
unique_ptr
means that the ownership rules surrounding the resource are dead easy.
Both enforce a set of ownership rules, but the rules for unique_ptr
are simple and local, the rules for shared_ptr
are complex and non-local. If you are in a situation where you are choosing between the two casually, then you aren't treating lifetime issues with the gravity they deserve.
If you have a pointer-like resource whose lifetime should be controlled simply, or even at some central location (type-wise) with complex logic around it, use unique_ptr
. The cost over a raw pointer is minimal, and it adds (enforced) documentation that this is the "owning" pointer to this resource.
If you must have a resource whose lifetime is the union of the lifetime of a bunch of other objects, all of whom have unrelated lifetimes, shared_ptr
can be considered. If your situation is so complex that a loop could possibly be formed, then naive shared_ptr
use is no longer a practical option.
shared_ptr
and weak_ptr
can also be used as a distributed lifetime notification system, where a central location stores a (mostly unique) shared_ptr
, and clients store weak_ptr
s. Local (non-stored) shared_ptr
s are created from the weak_ptr
s in order to check that the target resource still exists, then the resource is manipulated, then the local shared_ptr
is discarded. The goal here is to make (in a non-language enforced way) a unique_ptr
with weak shares, so reasoning about lifetime is only marginally harder than the unique_ptr
case.
shared_ptr
basically never "solves" the lifetime problem without you proving that it will solve your lifetime problems. It can make some parts of that proof marginally easier.
Upvotes: 0
Reputation: 24561
The rule of thumb is:
Raw pointers are OK in certain circumstances when they don't carry ownership - for instance as an input argument to a function:
void draw (const shape* sh) {
sh->draw();
}
...
std::unique_ptr<shape> ptr(new triangle);
draw(ptr.get());
Upvotes: 6
Reputation: 4357
A shared_ptr has the extra cost of construction/destruction of the pointer itself, if passed to a function, plus the reference counting mechanism.
Do not listen to anyone that says either smart pointers are always the way to go, nor to people who say raw pointers are always better. There are cases where smart pointers make sense, and cases where raw pointers are preferable.
For a more detailed and comprehensive read, I'll suggest you to visit: http://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters/
It covers all the points you raised and it is an easy read for the most part.
Upvotes: 0
Reputation: 5232
The problem with the shared_ptr
is, that, afaik, the reference counting is an atomic function, that means it not only counts the references, but also has locking functionality to ensure that the function is atomic. So at that point, yes, unique_ptr
is better to use, when you only need move functionality.
Personally, I dont use shared_ptr
alot, mostly normal pointers are enough. Imho smart pointers are only encourage getting lazy in memory management. I was in projects where smart pointers only caused race conditions when quitting the program, because nobody knew the order of destruction and these pointers referenced each others. For myself, I only use them if a lib of mine is putting pointers to the outside for which it is irrelevent when they get deleted (or in which order).
Upvotes: 3