std::unique_ptr: a Smart Pointer that Cannot be Copied

A std::unique_ptr owns of the object it points to and no other smart pointers can point to it. When the std::unique_ptr goes out of scope, the object is deleted. This is useful when you are working with a temporary, dynamically-allocated resource that can get destroyed once out of scope.

How to construct a std::unique_ptr

A std::unique_ptr is created like this:

std::unique_ptr<Type> p(new Type);

For example:

std::unique_ptr<int>    p1(new int);
std::unique_ptr<int[]>  p2(new int[50]);
std::unique_ptr<Object> p3(new Object("Lamp"));

It is also possible to construct std::unique_ptrs with the help of the special function std::make_unique...

std::make_unique<>()

Use std::make_unique<>() to create a unique_ptr. For example, instead of writing the following:

Employee* anEmployee = new Employee;

You should write:

auto anEmployee = std::make_unique<Employee>();

If your compiler is not yet C++14 compliant you can make your unique_ptr as follows. Note that you now have to specify the type, Employee, twice:

std::unique_ptr<Employee> anEmployee(new Employee);

You can now use the anEmployee smart pointer the same way as a normal pointer.

Some more examples:

std::unique_ptr<int>    p1 = std::make_unique<int>();
std::unique_ptr<int[]>  p2 = std::make_unique<int[]>(50);
std::unique_ptr<Object> p3 = std::make_unique<Object>("Lamp");

Note: If you can, always choose to allocate objects using std::make_unique.

One resource, one std::unique_ptr

I could say that std::unique_ptr is very jealous of the dynamic object it holds: you can't have multiple references to its dynamic data. For example:

void compute(std::unique_ptr<int[]> p) { ... }

int main()
{
    std::unique_ptr<int[]> ptr = std::make_unique<int[]>(1024);
    std::unique_ptr<int[]> ptr_copy = ptr; // ERROR! Copy is not allowed
    compute(ptr);  // ERROR! `ptr` is passed by copy, and copy is not allowed
}

This is done on purpose and it's an important feature of std::unique_ptr: there can be at most one std::unique_ptr pointing at any one resource. This prevents the pointer from being incorrectly deleted multiple times.

Technically this happens because a std::unique_ptr doesn't have a copy constructor: it might be obvious to you if you are familiar with move semantics.