When we talk about std::unique_ptr we must mention the idea of explicit resource ownership as well as the concept of a resource source and sink. By wrapping a pointer inside std::unique_ptr we state that whoever holds the std::unique_ptr owns the resource explicitly: has complete control over its lifetime. Prior to C++11 this was expressed using std::auto_ptr. Modern C++ deprecated std::auto_ptr and addressed its shortcomings by introducing the std::unique_ptr.

A source is a function that creates a resource then relinquishes its ownership; in other words, it gives the ownership to whoever called it, and from then on, the caller is responsible for releasing that resource.

A sink is a function which accepts a resource as a parameter and assumes ownership of it; in other words, it promises to release said resource once it’s done executing.

Transfer of ownership must be stated explicitly for named instances (variables of type std::unique_ptr) with std::move. Unnamed temporaries can be passed into a variable or as a function parameter without invoking std::move (this will be clearly illustrated in the code sample below).

Explicit ownership of a resource can be “upgraded” to shared ownership by std::move’ing the std::unique_ptr into a std::shared_ptr. It resets the std::unique_ptr to point back at nullptr and initializes the std::shared_ptr with reference count of 1 (also illustrated in the code below).

Worth mentioning is the fact that std::unique_ptr can own arrays of objects allocated with operator new. A partial specialization of std::unique_ptr template for array types also overloads operator[] for easy array element access; it mirrors the syntax of native arrays. However there are limitations of storing arrays inside std::unique_ptr: when creating an array of primitive types an initial value for each element cannot be specified (and each element ends up with an undefined value); when creating an array of user-defined types (classes and structs) said type must have a default constructor. Moreover the size of the array is lost: there is no way to query the std::unique_ptr and find out how many elements the array holds. For those reasons I recommend you stick with std::vector: it’s elements can be initialized with a default or custom value and you can always call size() on it.

The example program below, using inline comments, further details how to transfer the resource ownership and how to express the idea of source and sink funtions.

Complete listing on GitHub: unique.cpp and T.hpp. Merry Christmas and Happy New Year!

One Reply to “std::unique_ptr, or how to express explicit ownership”

  1. I think unique_ptr can be used to move pointers out of contexts of very high usage (dereferencing) by multiple threads into a context of usage by a single thread (e.g., cleanup thread). This would facilitate writing an object cleanup thread where there is assurance that only one thread is accessing the object in the unique_ptr.

Leave a Reply