7

I'm currently learning about the unique_ptr and shared_ptr types in C++. The advantages of smart pointers over raw pointers are apparent, and there are lots of explanations why you should prefer them over raw pointers. What I'm struggling to understand is why you would ever specifically choose to use a unique_ptr over a shared_ptr?

As far as I can tell, from the programmers perspective (ignoring implementation) , a unique_ptrjust seems like a special-case version of a shared_ptr where the reference count is restricted to one. So if I create a shared_ptr and only ever create a single reference, then I basically have the utility of a unique_ptr (with the ability to use the shared part in the future).

So what advantage does a unique_ptr give you? I should admit that I approach this as a Java programmer and a shared_ptr seems pretty darn close to the way Java works.

J-bob
  • 8,380
  • 11
  • 52
  • 85
  • 3
    It is cheaper to use (or, rather, it prohibits expensive usage) and it makes program logic way clearer and easier to reason about. Overall, most of the time you do not need `shared_ptr` in C++ programs with rather rather rare exceptions. – SergeyA Sep 30 '19 at 19:19
  • The advantage of `unique_ptr` is that it is pretty darn far to the way Java works. `unique_ptr` does not need to allocate or update reference counter in some implicitly created shared state object. – user7860670 Sep 30 '19 at 19:19
  • 1
    Both have their own advantages and disadvantages. It depends on what context you're using the pointer in. – Aryan Mediratta Sep 30 '19 at 19:24
  • Many answers here. https://stackoverflow.com/questions/6876751/ – Drew Dormann Sep 30 '19 at 19:25
  • 1
    `shared_ptr`s are indeed close to how Java works. They are also **costly**. – Drew Dormann Sep 30 '19 at 19:28
  • `shared_ptr` is unlike the way Java works: Java has no standard way to integrate reliable and timely cleanup of object in a class method called at the right time; any pattern based explicit method call creates the opportunity of releasing resources too early or not at all. OTOH Java has no "cycle" problem with automatic memory release (but cycles create problems with automatic execution in "finalizers" in any PL that has automatic GC that pretends to be able to run "finalizers"). – curiousguy Oct 03 '19 at 04:30

1 Answers1

10

a unique_ptr just seems like a special-case version of a shared_ptr where the reference count is restricted to one

This is not true, and is the crux of why you would use one or another. A shared_ptr is a reference counted pointer. In order for it to be thread safe it uses an atomic counter for the reference count. So that means for a shared_ptr you have the extra overhead of storing the reference counter, plus the execution overhead of checking/manipulating that counter in all the functions that affect it. This overhead can make a noticeable impact on performance

A unique_ptr, conversely, is a non reference counted pointer. It can get away without having a reference counter because it is not copyable. That means it is basically a zero cost abstraction for newing and deleteing a pointer.

So, if you never need to share ownership, or you can just move it from place to place, and you want self management, then you want a unique_ptr. This covers the vast majority of pointer use cases. When you truly need shared ownership then you can go ahead and use shared_ptr, but understand you suffer a performance penalty for that shared ownership.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • We shouldn't confuse the issue of shared atomic objects to the issue of effectively thread local atomic objects: profiling on common CPU shows that the cost of an atomic RMW operation is enormous compared to a simple read or write (or a sequence of these) *only* in the case where the cache line was previously not in our cache, which would very rarely happen if the atomic object was only manipulated locally. (Waiting for another cache to transfer ownership to us, while blocking all other memory operations, has huge impact.) Local RMW is merely slow. – curiousguy Oct 03 '19 at 04:39