TL;DR Use the smart-pointer to get value semantics on a heap resource. At the cost of some extra copying, your code will be simpler and easier to reason about. value_ptr Choose which smart-pointer to use with this cheat-sheet. A implementation of can be found on . value_ptr GitHub Introduction Language features like templates, lambdas and lexically-scoped destructors empower C++ programmers to write higher-order containers to handle an object’s lifetime and side-effects, documenting them in an understandable way in the type-system. With smart-pointers, encoding ownership semantics and managing resources has never been easier. We can find smart-pointers in the standard library for the most common use-cases, however none of these smart-pointers provides value semantics. This article will introduce the , alongside some motivating examples. value_ptr But first, let’s take a look at the functionality that the C++ 11 standard library already offers: (Dumb) Raw Pointers Yes, raw pointers can be still used, but you should avoid them if a smart-pointer is applicable. This is because raw pointers do not convey any information about a resource’s ownership model. Furthermore, allocation and deallocation must be managed by the programmer, which may lead to bugs like double-delete or memory-leaks. Take a look at this code: From just three lines, there are so many unanswered questions: Can be and do I have to check? x nullptr Is managed? Can I ? I ? x delete x Must delete x If I delete before , is still valid? y foo foo If gets destroyed, will be deleted? foo y Used correctly, a smart-pointer makes these clear. unique_ptr manages the lifetime of an resource by taking sole ownership of it and binding that to its lexical scope. While copying is not possible, the ownership can be transferred via . unique_ptr std::move Use when: unique_ptr You want to tie the lifetime of a heap resource to a lexical scope You want to enforce that the resource only has one owner at a time Example shared_ptr allows for multiple resource owners by counting the number of references under management. The container’s copy-constructor increments the counter and decrements it on destruction. If the counter hits zero, then the resource will be disposed. shared_ptr Use when: shared_ptr You want to share ownership between multiple references You want to dispose of a resource automatically when it is no longer used You don’t have cyclic dependencies The overhead of reference counting is acceptable Example weak_ptr We saw that we can use with multiple owners, but what happens if we have cycles in the ownership graph? In this case, we would leak memory as the reference counter would never hit zero! The owners in the cycle would keep each-other alive. shared_ptr This is where comes into play. is like but it does not increment the reference counter. If you replace the cycle-branch in your ownership graph with a , then reference counting will work correctly. weak_ptr weak_ptr shared_ptr weak_ptr Example Use when: weak_ptr You absolutely must have a cyclic ownership graph Introducing value_ptr Value semantics make your code easier to reason about because unlike pointers, ownership must be strictly hierarchical and exclusive. allows us to enforce those semantics on a copyable resource on the heap. value_ptr How it Works has exclusive ownership of a resource on the heap. value_ptr When you assign one to another, a new object is constructed that points to of the previous ’s resource. value_ptr value_ptr its own copy value_ptr The resource is destroyed when the leaves its lexical scope. value_ptr No memory is shared, so is inherently thread-safe. value_ptr A modern compiler is smart enough to remove most redundant copies. Example 1 — Recursive Data Types Recursive types like trees must be implemented via a pointer in C++ so the layout in memory can be computed at compile-time. However, despite using a pointer, we might still want the simplicity of value-semantics: Example 2 — The PImpl Pattern Sometimes we want to separate the interface of a class from its implementation. This might be to hide code behind a compiled library, or to enforce a constant stack-size. Since the lifetime is bound to the owner, a smart-pointer is appropriate here, but what semantics do we want to have? Unlike and , gives us value semantics. shared_ptr unique_ptr value_ptr Header Translation-unit More Resources About the PImpl Pattern PImpl, Rule of Zero and Scott Meyers The Fast PImpl Idiom PImpl You C++ Code Implementing value_ptr You might have noticed that is similar to , but with a different copy-constructor. Whilst copying a is forbidden, copying a will create a copy of the resource. Thus, we can implement by leveraging and a copy function. value_ptr unique_ptr unique_ptr value_ptr value_ptr unique_ptr This is what we have done; , or test-drive our implementation with : take a look on GitHub Buckaroo buckaroo install loopperfect/valuable Summary Value semantics are easy to reason about, and are often useful even for heap objects. The C++ standard library does not provide a smart-pointer with value semantics, but C++ has the features to allow us to roll-our-own. Can’t decide which smart-pointer to use? Here’s a quick chart: