This blog was last modified 328 days before.

There are three different types of smart pointers in C++.

  • unique_ptr
  • shared_ptr
  • weak_ptr

Checkout Microsoft Learn - Smart Pointers for basics of this smart pointer class.

Init Smart Pointers

In Microsoft Learn, it widely use the following patterns:

make_unique<T> pValue(new T(...));

In this case, it's ok, but consider the following situation:

// func declaration
func(unique_ptr<T> pValue1, unique_ptr<T> pValue1);

// call func()
func(unique_ptr<T>(new T(1)), unique_ptr<T>(new T(2)));

Looks great. But what if one of the allocation (new T(1) or new T(2)) failed? This may lead to memory leak. For more info, check out this Question on StackOverflow.

make_unique

To avoid memory leak in some specified cases, we should use make_unique() instead:

auto pValue = make_unique<T>(T());

Notice that this time we don't need to use new keyword anymore.

Convertion between pointers

We mainly talking about unique_ptr and smart_ptr. Generally we have:

  • unique_ptr -> shared_ptr (Allowed)
  • shared_ptr -> unique_ptr (Not Allowed)

This behaviour concur with intuitives, because sinces shared_ptr could be shared in different scope and even in different threads, it's nearly impossible to transfer its whole ownership.

To convert a unique_ptr to shared_ptr, we need to give up the ownership of the unique_ptr and move it to a compatible type shared_ptr:

// create unique_ptr
unique_ptr<int> pValue = make_unique<int>();
// transfer ownership to a shared_ptr object
shared_ptr<int> pShared(std::move(pValue));

*pValue; // Don't do this, pValue is invalid here! Use pShared instead.

Code example:

#include <iostream>
#include <memory>

using std::cout, std::endl, std::move;
using std::make_unique, std::make_shared;
using std::unique_ptr, std::shared_ptr, std::weak_ptr;

int main()
{
    auto pValue = make_unique<int>(100);
    shared_ptr<int> pShared(std::move(pValue));
    cout << *pShared << endl; // Output: 100
    cout << *pValue << endl; // will cause segment fault.
    return 0;
}

Refs