I have a project and I want make smart pointers usage better.
The main idea is to use them when returning new object from function. The question is what smart pointer to use? auto_ptr or shared_ptr from boost? As I know, auto_ptr is slower but it can fall back to the 'pure' pointer.
And if I'll use smart pointer in place where I don't need it, would it make the perfomance slower?
What makes you think auto_ptr is slower than shared_ptr? Typically I would expect the reverse to be true, since shared_ptr needs to update the reference count.
As for which you should use, different smart pointers imply different ownership semantics. Ownership implies the responsibility to delete the object when it is no longer needed.
A raw pointer implies no ownership; a program that uses smart pointers correctly may still make use of raw pointers in a lot of places where ownership is not intended (for example, if you need to pass an optional reference to an object into a function, you would often use a raw pointer).
scoped_ptr implies single (ie, non-shared), non-transferable ownership.
auto_ptr implies single (ie, non-shared) transferable ownership. This is the smart pointer I would use to return a newly constructed object from a function (the function is transferring the object to its caller). auto_ptr suffers from the disadvantage that due to limitations of the language when auto_ptr was defined, it is difficult to use correctly (this has given it a very bad reputation, though the intended purpose of a smart pointer with single, transferable ownership semantics was and is both valid and useful).
unique_ptr has the same semantics as auto_ptr, but uses new C++0x features (rvalue references) to make it a lot safer (less prone to incorrect use) than auto_ptr. If you are developing on a platform where unique_ptr is available, then you should use it instead of auto_ptr.
shared_ptr implies shared ownership. In my opinion this is over-used. It does have many valid uses, but it should not simply be used as a default option.
I would also add that shared_ptr is often used with STL containers because the other smart pointer classes do not achieve their intended function in that context (due to copying of values internally within the container). This often leads to use of shared_ptr where shared ownership is not really the intended meaning. In these cases, I suggest (where possible) using the boost pointer-container classes (ptr_vector, ptr_map and so on), which provide the (commonly desired) semantics of a container with transferable, but single (non-shared) ownership.
You should always think about the ownership of your objects: in most cases, with a clean system design, each object has one obvious owner, and ownership does not need to be shared. This has the advantage that it is easy to see exactly where and when objects will be freed, and no reference counting overhead is needed.
[edited to note the new unique_ptr]
You probably should use shared_ptr<>. It's hard to be more specific without knowing what exactly you want to do. Best read its documentation and see if it does what you need.
The performance difference will most likely be negligible. Only in extreme cases there might me an noticeable impact, like when copying these pointers many million times each second.
I prefer shared_ptr, auto_ptr can cause a lot of trouble and its use is not too intuitive. If you expect this object to be inserted on a STL container, so you certainly want to use shared_ptr.
Abot the performance you have a cost, but this is minimal and you can ignore it most of the time.
Depends.
Shared pointers have a better use than auto_ptr which have the unusual characteristic of changing ownership on assignments.
Also auto_ptr can not be used in containers.
Also you can not use auto_ptr as return values if you do not want to transfer ownership.
Shared pointers have all the benefits of smart pointers, have overloaded the relevant operators to act like a pointer and can be used in containers.
Having said that, they are not cheap to use.
You must analyze your needs to decide if you actually gain something by avoiding the shared_pointer implementation overheads
Use only shared_ptr. With auto_ptr you can have ONLY ONE reference to your object. Also auto_ptr isn't slower it must work faster than shared_ptr.
To not ask such questions you need to know, how this smart pointers work.
auto_ptr just storing pointer to your object and destroying it in it's destructor.
The problem of auto_ptr is that when you are trying to copy it it's stopping to point to your object.
For example
auto_ptr a_ptr(new someClass);
auto_ptr another_ptr=aptr;// after this another_ptr is pointing to your class, but a_ptr isn't pointing to it anymore!
This is why I don't recomend you to use auto_ptr.
Shared pointer counting how much smart pointers are pointing to your object and destroying your object when there is no more pointers to it. That's why you can have more than 1 pointer pointing to your object.
But Shared pointer also isn't perfect. And if in your program you have cyclic graph (when you have classes A and B and A have a member shared_ptr wich points to B and B have or B's member objects have shared_ptr pointing to A) than A and B will never deleted and you will have memory lick.
To write correct code with shared_ptr you need to be careful and also use weak_ptr.
For more information look at here http://www.boost.org/doc/libs/1_45_0/libs/smart_ptr/smart_ptr.htm
Related
Question: Are there any compelling reasons to use naked pointers for non-owning resources or should we be using weak_ptr?
CPP.reference states
std::weak_ptr models temporary ownership: when an object needs to be accessed only if it exists, and it may be deleted at any time by someone else
But then, in the accepted answer for Which kind of pointer do I use when? we have the statement:
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.
This answer is followed by a lot of back-and-forth about the use of naked pointers, with no real resolution. I can't see any reason for using dumb pointers. Am I missing something?
A weak_ptr has a very specific purpose: to break shared_ptr cycles. As an example, std::enable_shared_from_this is based on letting an object contain a weak_ptr to itself. If it directly contained a shared_ptr then that would create a cycle, so instead it has a weak_ptr.
You use a weak_ptr where you would otherwise have had a shared_ptr. The weak_ptr has a higher cost because in addition to the costs of shared_ptr there is the object existence checking that produces a shared_ptr, or not. Also it's a more complex beast so that it's easier to use incorrectly.
I can't think of any way that weak_ptr has anything to do with “temporary ownership” (except that after checking of existence and using a produced shared_ptr, that's one temporary shared ownership, which is repeated again and again for each use). For example, std::enable_shared_from_this has nothing to do with temporary ownership. Ordinarily I would just ignore a source of such a claim, and advice others to ignore it, but cppreference.com is about the best we have in the way of a free online C++ reference. It's odd that it contains a nonsense statement. But, nothing's prefect, as I once remarked to Bjarne in clc++, whereupon he corrected my speling of “prefect”. Hm! Well.
I don't know of any advantage in using a raw pointer rather than a weak_ptr, where a weak_ptr is what's required. A raw pointer can't do a weak_ptr's job of holding on to a shared_ptr's control block, so it seems to me that the mere idea of replacing a weak_ptr with a raw pointer is nonsense. But then, the day one stops being surprised by learning things one could never have thought of, is the day one is dead, and so it may be the case that there is some obscure-to-me such use.
Also, there is no advantage in using a weak_ptr where a raw pointer is what's required. Rather, the weak_ptr introduces a relatively speaking enormous cost, of control block allocation and reference counting. So I can't think of any situation where it would make sense to replace raw pointers with weak_ptr, and I don't expect this to be a case where I learn otherwise.
a weak pointer actually has very little usage. A weak pointer is only useful, if you need it's lock function (transform the pointer into a shared pointer, to prevent garbage collection while you are operating on it). Non owning pointers best, if you just use raw pointer, because of the overhead shared and weak pointer have.
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?
The rule of thumb is:
If you can, use a stack based object directly or by a reference instead of using pointers.
Else, if you don't have to deal with shared ownership (usually you don't) use unique_ptr - it is not only faster, but also safer (no circular references).
Else, if you do have shared ownership, use shared_ptr
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());
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).
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.
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.
shared_ptr means that the ownership rules surrounding the resource are complicated. Understanding them requires tracking down the lifetime of all shared_ptrs 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_ptrs. Local (non-stored) shared_ptrs are created from the weak_ptrs 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.
Ok, so the last time I wrote C++ for a living, std::auto_ptr was all the std lib had available, and boost::shared_ptr was all the rage. I never really looked into the other smart pointer types boost provided. I understand that C++11 now provides some of the types boost came up with, but not all of them.
So does someone have a simple algorithm to determine when to use which smart pointer? Preferably including advice regarding dumb pointers (raw pointers like T*) and the rest of the boost smart pointers. (Something like this would be great).
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 deleteing it (with the default_deleter). 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 template unique_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.
Deciding what smart pointer to use is a question of ownership. When it comes to resource management, object A owns object B if it is in control of the lifetime of object B. For example, member variables are owned by their respective objects because the lifetime of member variables is tied to the lifetime of the object. You choose smart pointers based on how the object is owned.
Note that ownership in a software system is separate from ownership as we would think of it outside of software. For example, a person might "own" their home, but that doesn't necessarily mean that a Person object has control over the lifetime of a House object. Conflating these real world concepts with software concepts is a sure-fire way to program yourself into a hole.
If you have sole ownership of the object, use std::unique_ptr<T>.
If you have shared ownership of the object...
- If there are no cycles in ownership, use std::shared_ptr<T>.
- If there are cycles, define a "direction" and use std::shared_ptr<T> in one direction and std::weak_ptr<T> in the other.
If the object owns you, but there is potential of having no owner, use normal pointers T* (e.g. parent pointers).
If the object owns you (or otherwise has guaranteed existence), use references T&.
Caveat: Be aware of the costs of smart pointers. In memory or performance limited environments, it could be beneficial to just use normal pointers with a more manual scheme for managing memory.
The costs:
If you have a custom deleter (e.g. you use allocation pools) then this will incur overhead per pointer that may be easily avoided by manual deletion.
std::shared_ptr has the overhead of a reference count increment on copy, plus a decrement on destruction followed by a 0-count check with deletion of the held object. Depending on the implementation, this can bloat your code and cause performance issues.
Compile time. As with all templates, smart pointers contribute negatively to compile times.
Examples:
struct BinaryTree
{
Tree* m_parent;
std::unique_ptr<BinaryTree> m_children[2]; // or use std::array...
};
A binary tree does not own its parent, but the existence of a tree implies the existence of its parent (or nullptr for root), so that uses a normal pointer. A binary tree (with value semantics) has sole ownership of its children, so those are std::unique_ptr.
struct ListNode
{
std::shared_ptr<ListNode> m_next;
std::weak_ptr<ListNode> m_prev;
};
Here, the list node owns its next and previous lists, so we define a direction and use shared_ptr for next and weak_ptr for prev to break the cycle.
Use unique_ptr<T> all the time except when you need reference counting, in which case use shared_ptr<T> (and for very rare cases, weak_ptr<T> to prevent reference cycles). In almost every case, transferrable unique ownership is just fine.
Raw pointers: Good only if you need covariant returns, non-owning pointing which can happen. They're not terrifically useful otherwise.
Array pointers: unique_ptr has a specialization for T[] which automatically calls delete[] on the result, so you can safely do unique_ptr<int[]> p(new int[42]); for example. shared_ptr you'd still need a custom deleter, but you wouldn't need a specialized shared or unique array pointer. Of course, such things are usually best replaced by std::vector anyway. Unfortunately shared_ptr does not provide an array access function, so you'd still have to manually call get(), but unique_ptr<T[]> provides operator[] instead of operator* and operator->. In any case, you have to bounds check yourself. This makes shared_ptr slightly less user-friendly, although arguably the generic advantage and no Boost dependency makes unique_ptr and shared_ptr the winners again.
Scoped pointers: Made irrelevant by unique_ptr, just like auto_ptr.
There's really nothing more to it. In C++03 without move semantics this situation was very complicated, but in C++11 the advice is very simple.
There are still uses for other smart pointers, like intrusive_ptr or interprocess_ptr. However, they're very niche and completely unnecessary in the general case.
Cases of when to use unique_ptr:
Factory methods
Members that are pointers (pimpl included)
Storing pointers in stl containters (to avoid moves)
Use of large local dynamic objects
Cases of when to use shared_ptr:
Sharing objects across threads
Sharing objects in general
Cases of when to use weak_ptr:
Large map that acts as a general reference (ex. a map of all open sockets)
Feel free to edit and add more
I have some questions about smart pointers implemented in boost library.
Is the only diffrence between shared_ptr and scoped_ptr that scoped_ptr doesn't have copy constructor and shared_ptr has it?
Should i use then scoped_ptr instead of shared_ptr always when object doesn't call copy constructor?
I also doesn't understand idea of shared/scoped array. Can't I just use std::vector instead of it?
Is the only diffrence between shared_ptr and scoped_ptr that
scoped_ptr doesn't have copy constructor and shared_ptr has it?
The difference is more fundamental than that; it has to do with how the smart pointers own the object it points to. What makes smart pointers different from dumb pointers is that the concept of ownership is a core component of their function. The ownership semantics is what differentiates the different kinds of smart pointers.
Because smart pointers "own" the thing they point to, they can do useful things like deleting objects when the smart pointers go away (this is made possible using only the rules of the language; no compiler magic is needed). This way, memory management can be made almost automatic in C++ (despite claims to the contrary, there's very little manual memory management required in modern C++).
shared_ptr implements reference-counting
semantics for
memory management. Multiple shared_ptrs can own a single object. A
shared_ptr going away does not necessarily delete the object it
points to because there may be another shared_ptr owning the
object. The last shared_ptr that owns an object and goes away will
delete the object it owns.
scoped_ptr implements exclusive-ownership semantics. Only one
scoped_ptr can own any one object. When a scoped_ptr goes away,
it will always delete the object it owns (because there's only one
owner). It's typically used as a lightweight RAII mechanism for
objects allocated on the free store.
The array versions (shared_array and scoped_array) have essentially the same semantics, but are designed specifically for arrays e.g. they use delete[] instead of delete, implements the array subscript operator, etc.
shared_ptr and shared_array also allows you to specify a custom deleter, if the default delete behavior is not appropriate for the object. scoped_ptr and scoped_array do not have that ability, since they are quite lightweight compared to shared_ptr and shared_array.
In C++11, the newest and current version of C++, there's also a unique_ptr, which is just like scoped_ptr except that you can transfer the ownership of an object to another unique_ptr. In C++03, an older but more widely supported version of C++, there's auto_ptr which is equivalent to unique_ptr except it was easy to use it in an unsafe manner by accident (which is why it is deprecated in C++11).
Should i use then scoped_ptr instead of shared_ptr always when object
doesn't call copy constructor?
Which one you choose doesn't depend on the presence of the copy-constructor, since shared_ptr and scoped_ptr does not require the object to be copy-constructible. You pick the one depending on the required ownership semantics. If the object will have multiple owners, you use shared_ptr. If the object will only have one owner and the object's existence lasts only within a scope, use scoped_ptr (hence the name scoped_ptr).
I also doesn't understand idea of shared/scoped array. Can't I just
use std::vector instead of it?
std::vector does not implement reference-counting semantics like shared_array does. std::vector is more like scoped_array, but can be copied. When you copy a std::vector, you also copy all of the elements it contains. That's not the case for scoped_array. std::vector also has functions that allow you to manipulate and examine its contents (e.g. push_back, insert, erase, etc.), but is much more heavyweight than scoped_array.
Yes. scoped_ptr does not allow for copies while shared_ptr does. But this "simple" difference makes a world of impact on both the implementation and the usage of the smart pointer.
scoped_ptr is faster and lighter than shared_ptr because no reference counting is involved. shared_ptr will count the number of assignments and not delete the object until all references have expired/gone out of scope.
Now your question regarding vectors implies that you're actually not familiar with the the concept of dynamic allocation and the difference between that and static allocation on the static. You really should look into reading a primer on C(++) and look into the reasons for dynamic allocation and when you need it.
A vector stores a list of objects. A XXX_ptr stores a pointer to a (single) dynamically-allocated object. Apples and oranges.
If you allocate memory, you can put the newly created pointer in a scoped pointer, so that IF the malloc/noew fails, the memory will be freed. This is how I usally uses it, or if it's an object that needs to be allocated on the heap, but that I want to treat it as a stack object in terms of that it will only be alive until the end of the scope.
The shared pointer is if you want to pass the pointer around and allow the object to have multiple owners. Then none of the owners needs to take responibility of the object and they can all just stop using it and be sure that it will be freed correclty. (you don't wanna free an object that you know is used by someone else)
I'd say you're thinking about it the wrong way. The question isn't whether you do call the copy constructor -- it's whether you need to call the copy constructor. In other words, you should be deciding whether to use shared_ptr or scoped_ptr not based on reading your code but based on thinking about object ownership and what objects' lifetimes should be.
Say you have an object that you want to create on the heap, not on the stack, for whatever reason (maybe it's too big to be on the stack, maybe you might want to replace it with a different object at some point, maybe you want it to be initialized late) but its lifetime should never be longer than its containing scope. A common example of this is instance variables in a class: they should often be deleted when the object they are in is deleted. Then, you should use scoped_ptr.
But sometimes you don't know when an object will be safe to delete in advance. For instance, consider an object in a lookup table. You want to return it in response to lookups, but what happens when it's deleted -- could someone still be using the object who looked it up previously? In cases like this, you can use shared_ptr, which shares the objects ownership so that it only gets deleted when nobody has a copy of the pointer anymore.
So why does anyone ever use scoped_ptr instead of shared_ptr? First of all, knowing when the destructor gets called is one of the big advantages of non-memory-managed languages like C++. Maybe the destructor is expensive, or maybe it frees a resource; it's nice to know when these things happen. Also, with shared_ptr, there's the potential for memory leaks if you create a circular reference by accident.
In general, almost every pointer you have should be "owned" -- there should be a single place in your code that news and deletes it. scoped_ptr is great for this; when you want an owned object to be passed around to non-owners you can use a bare pointer. But if you absolutely need an object's ownership to be shared, use shared_ptr -- as long as you're careful to use it correctly!
As for scoped/shared arrays, you can certainly use std::vector, but arrays are cheaper and sometimes people want the performance benefit.
shared_ptr is very different from scoped_ptr. scoped_ptr (which is now standardized in C++11 as std::unique_ptr) is simply a RAII-style smart pointer which takes ownership of a resource and then deallocates the owned resource when the pointer goes out of scope.
A shared_ptr however, may share ownership of the resource with other instances of shared_ptr. The resource stays alive as long as one or more shared_ptr instances own it. This is an automatic memory-management technique, (a form of garbage-collection) known as reference counting. It basically provides the same effect as more advanced garbage collection algorithms, except unlike other garbage collection techniques, it doesn't handle circular references.
As for using std::vector versus boost::scoped_array, yeah - scoped_array doesn't really offer much of an advantage. However, boost::shared_array offers reference counting semantics, just like shared_ptr.
Ok, so the last time I wrote C++ for a living, std::auto_ptr was all the std lib had available, and boost::shared_ptr was all the rage. I never really looked into the other smart pointer types boost provided. I understand that C++11 now provides some of the types boost came up with, but not all of them.
So does someone have a simple algorithm to determine when to use which smart pointer? Preferably including advice regarding dumb pointers (raw pointers like T*) and the rest of the boost smart pointers. (Something like this would be great).
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 deleteing it (with the default_deleter). 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 template unique_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.
Deciding what smart pointer to use is a question of ownership. When it comes to resource management, object A owns object B if it is in control of the lifetime of object B. For example, member variables are owned by their respective objects because the lifetime of member variables is tied to the lifetime of the object. You choose smart pointers based on how the object is owned.
Note that ownership in a software system is separate from ownership as we would think of it outside of software. For example, a person might "own" their home, but that doesn't necessarily mean that a Person object has control over the lifetime of a House object. Conflating these real world concepts with software concepts is a sure-fire way to program yourself into a hole.
If you have sole ownership of the object, use std::unique_ptr<T>.
If you have shared ownership of the object...
- If there are no cycles in ownership, use std::shared_ptr<T>.
- If there are cycles, define a "direction" and use std::shared_ptr<T> in one direction and std::weak_ptr<T> in the other.
If the object owns you, but there is potential of having no owner, use normal pointers T* (e.g. parent pointers).
If the object owns you (or otherwise has guaranteed existence), use references T&.
Caveat: Be aware of the costs of smart pointers. In memory or performance limited environments, it could be beneficial to just use normal pointers with a more manual scheme for managing memory.
The costs:
If you have a custom deleter (e.g. you use allocation pools) then this will incur overhead per pointer that may be easily avoided by manual deletion.
std::shared_ptr has the overhead of a reference count increment on copy, plus a decrement on destruction followed by a 0-count check with deletion of the held object. Depending on the implementation, this can bloat your code and cause performance issues.
Compile time. As with all templates, smart pointers contribute negatively to compile times.
Examples:
struct BinaryTree
{
Tree* m_parent;
std::unique_ptr<BinaryTree> m_children[2]; // or use std::array...
};
A binary tree does not own its parent, but the existence of a tree implies the existence of its parent (or nullptr for root), so that uses a normal pointer. A binary tree (with value semantics) has sole ownership of its children, so those are std::unique_ptr.
struct ListNode
{
std::shared_ptr<ListNode> m_next;
std::weak_ptr<ListNode> m_prev;
};
Here, the list node owns its next and previous lists, so we define a direction and use shared_ptr for next and weak_ptr for prev to break the cycle.
Use unique_ptr<T> all the time except when you need reference counting, in which case use shared_ptr<T> (and for very rare cases, weak_ptr<T> to prevent reference cycles). In almost every case, transferrable unique ownership is just fine.
Raw pointers: Good only if you need covariant returns, non-owning pointing which can happen. They're not terrifically useful otherwise.
Array pointers: unique_ptr has a specialization for T[] which automatically calls delete[] on the result, so you can safely do unique_ptr<int[]> p(new int[42]); for example. shared_ptr you'd still need a custom deleter, but you wouldn't need a specialized shared or unique array pointer. Of course, such things are usually best replaced by std::vector anyway. Unfortunately shared_ptr does not provide an array access function, so you'd still have to manually call get(), but unique_ptr<T[]> provides operator[] instead of operator* and operator->. In any case, you have to bounds check yourself. This makes shared_ptr slightly less user-friendly, although arguably the generic advantage and no Boost dependency makes unique_ptr and shared_ptr the winners again.
Scoped pointers: Made irrelevant by unique_ptr, just like auto_ptr.
There's really nothing more to it. In C++03 without move semantics this situation was very complicated, but in C++11 the advice is very simple.
There are still uses for other smart pointers, like intrusive_ptr or interprocess_ptr. However, they're very niche and completely unnecessary in the general case.
Cases of when to use unique_ptr:
Factory methods
Members that are pointers (pimpl included)
Storing pointers in stl containters (to avoid moves)
Use of large local dynamic objects
Cases of when to use shared_ptr:
Sharing objects across threads
Sharing objects in general
Cases of when to use weak_ptr:
Large map that acts as a general reference (ex. a map of all open sockets)
Feel free to edit and add more