269

Possible Duplicates:
pimpl: shared_ptr or unique_ptr
smart pointers (boost) explained

Could someone explain differences between shared_ptr and unique_ptr?

Community
  • 1
  • 1
smallB
  • 14,808
  • 29
  • 97
  • 144
  • [smart pointers boost explained](http://stackoverflow.com/questions/569775/smart-pointers-boost-explained) – legion Jul 29 '11 at 17:31

4 Answers4

554

Both of these classes are smart pointers, which means that they automatically (in most cases) will deallocate the object that they point at when that object can no longer be referenced. The difference between the two is how many different pointers of each type can refer to a resource.

When using unique_ptr, there can be at most one unique_ptr pointing at any one resource. When that unique_ptr is destroyed, the resource is automatically reclaimed. Because there can only be one unique_ptr to any resource, any attempt to make a copy of a unique_ptr will cause a compile-time error. For example, this code is illegal:

unique_ptr<T> myPtr(new T);       // Okay
unique_ptr<T> myOtherPtr = myPtr; // Error: Can't copy unique_ptr

However, unique_ptr can be moved using the new move semantics:

unique_ptr<T> myPtr(new T);                  // Okay
unique_ptr<T> myOtherPtr = std::move(myPtr); // Okay, resource now stored in myOtherPtr

Similarly, you can do something like this:

unique_ptr<T> MyFunction() {
    unique_ptr<T> myPtr(/* ... */);

    /* ... */

    return myPtr;
}

This idiom means "I'm returning a managed resource to you. If you don't explicitly capture the return value, then the resource will be cleaned up. If you do, then you now have exclusive ownership of that resource." In this way, you can think of unique_ptr as a safer, better replacement for auto_ptr.

shared_ptr, on the other hand, allows for multiple pointers to point at a given resource. When the very last shared_ptr to a resource is destroyed, the resource will be deallocated. For example, this code is perfectly legal:

shared_ptr<T> myPtr(new T);       // Okay
shared_ptr<T> myOtherPtr = myPtr; // Sure!  Now have two pointers to the resource.

Internally, shared_ptr uses reference counting to track how many pointers refer to a resource, so you need to be careful not to introduce any reference cycles.

In short:

  1. Use unique_ptr when you want a single pointer to an object that will be reclaimed when that single pointer is destroyed.
  2. Use shared_ptr when you want multiple pointers to the same resource.

Hope this helps!

templatetypedef
  • 328,018
  • 92
  • 813
  • 992
  • 21
    `unique_ptr` can be a little buggy regarding deleters. `shared_ptr` will always do "the right thing", as long it was created with `make_shared`. But if you create a `unique_ptr`, then convert it to `unique_ptr`, and if Derived is virtual and Base is not, then the pointer will be deleted through the wrong type and there can be undefined behaviour. This can be fixed with an appropriate deleter-type in the `unique_ptr`, but the default is to use the riskier version because it is a little more efficient. – Aaron McDaid Aug 10 '15 at 20:45
  • 7
    @AaronMcDaid By default `unique_ptr` will behave like a raw pointer that you can't forget to `delete`: if you forget to make the dtor virtual, it's on you. – curiousguy Jun 30 '18 at 18:00
  • 1
    I prefer using `make_unique` instead of `new`. It is cleaner, safer and more efficient. – SubMachine Oct 27 '18 at 14:18
  • 1
    @templatetypedef could you give an example of how to capture the return value of your `MyFunction()` into another pointer in the caller's scope? – Vassilis Nov 11 '18 at 17:05
  • such a great answer – tae ha Mar 08 '21 at 13:20
81

unique_ptr is the light-weight smart pointer of choice if you just have a dynamic object somewhere for which one consumer has sole (hence "unique") responsibility -- maybe a wrapper class that needs to maintain some dynamically allocated object. unique_ptr has very little overhead. It is not copyable, but movable. Its type is template <typename D, typename Deleter> class unique_ptr;, so it depends on two template parameters.

unique_ptr is also what auto_ptr wanted to be in the old C++ but couldn't because of that language's limitations.

shared_ptr on the other hand is a very different animal. The obvious difference is that you can have many consumers sharing responsibility for a dynamic object (hence "shared"), and the object will only be destroyed when all shared pointers have gone away. Additionally you can have observing weak pointers which will intelligently be informed if the shared pointer they're following has disappeared.

Internally, shared_ptr has a lot more going on: There is a reference count, which is updated atomically to allow the use in concurrent code. Also, there's plenty of allocation going on, one for an internal bookkeeping "reference control block", and another (often) for the actual member object.

But there's another big difference: The shared pointers type is always template <typename T> class shared_ptr;, and this is despite the fact that you can initialize it with custom deleters and with custom allocators. The deleter and allocator are tracked using type erasure and virtual function dispatch, which adds to the internal weight of the class, but has the enormous advantage that different sorts of shared pointers of type T are all compatible, no matter the deletion and allocation details. Thus they truly express the concept of "shared responsibility for T" without burdening the consumer with the details!

Both shared_ptr and unique_ptr are designed to be passed by value (with the obvious movability requirement for the unique pointer). Neither should make you worried about the overhead, since their power is truly astounding, but if you have a choice, prefer unique_ptr, and only use shared_ptr if you really need shared responsibility.

Ben Lings
  • 27,150
  • 13
  • 69
  • 79
Kerrek SB
  • 428,875
  • 83
  • 813
  • 1,025
  • 4
    "designed to be passed by value" ?? – Ajay Nov 29 '13 at 05:56
  • 4
    Upvoted since I was puzzled about where the shared_ptr's reference counter could actually be (after all, multiple shared_ptrs and a single shared resource means a single shared reference counter too right? So the counter can't be contained within a shared_ptr). This is the first shared_ptr explanation that I've seen that answers my question; A separate reference counter is allocated. Presumably it's allocated once at count 0->1 and freed once at count 1->0, just like the controlled resource. – Bill Forster Oct 07 '15 at 02:53
  • 1
    How can you pass it by value if you cannot copy it? – splinter123 Jun 03 '16 at 22:00
  • 12
    @splinter123: By moving it! – Kerrek SB Jun 03 '16 at 22:17
  • @KerrekSB "you can have observing weak pointers which will intelligently be informed if the shared pointer they're following has disappeared", Could you please elaborate how? – Farzan Sep 17 '19 at 20:07
  • @KerrekSB "By moving it", Does it mean when passing a unique_ptr to a function by value then the caller has no access to the original unique_ptr? – Farzan Sep 17 '19 at 20:10
  • 1
    @Farzan: Yes, precisely. Either you call the function with a temporary (to which you have no access by definition), or you need to pass something like `std::move(x)` as an argument, which means that `x` is then moved-from. – Kerrek SB Sep 17 '19 at 22:59
21

unique_ptr
is a smart pointer which owns an object exclusively.

shared_ptr
is a smart pointer for shared ownership. It is both copyable and movable. Multiple smart pointer instances can own the same resource. As soon as the last smart pointer owning the resource goes out of scope, the resource will be freed.

Alok Save
  • 190,255
  • 43
  • 403
  • 518
10

When wrapping a pointer in a unique_ptr you cannot have multiple copies of unique_ptr. The shared_ptr holds a reference counter which count the number of copies of the stored pointer. Each time a shared_ptr is copied, this counter is incremented. Each time a shared_ptr is destructed, this counter is decremented. When this counter reaches 0, then the stored object is destroyed.

Ajay
  • 16,823
  • 9
  • 50
  • 94
neodelphi
  • 2,438
  • 1
  • 13
  • 21
  • The counter is an implementation detail. What matters is that the "family" of `shared_ptr` that are copies of each other is able to determine when the last member of the family is destructed. – curiousguy Jun 30 '18 at 18:12