The class template [std::shared_ptr](<>) defines a shared pointer that is able to share ownership of an object with other shared pointers. This contrasts to [std::unique_ptr](<>) which represents exclusive ownership.

The sharing behavior is implemented through a technique known as reference counting, where the number of shared pointers that point to the object is stored alongside it. When this count reaches zero, either through the destruction or reassignment of the last std::shared_ptr instance, the object is automatically destroyed.

`// Creation: 'firstShared' is a shared pointer for a new instance of 'Foo' 
std::shared_ptr<Foo> firstShared = std::make_shared<Foo>(/*args*/);`

To create multiple smart pointers that share the same object, we need to create another shared_ptr that aliases the first shared pointer. Here are 2 ways of doing it:

std::shared_ptr<Foo> secondShared(firstShared);  // 1st way: Copy constructing
std::shared_ptr<Foo> secondShared;
secondShared = firstShared;                      // 2nd way: Assigning

Either of the above ways makes secondShared a shared pointer that shares ownership of our instance of Foo with firstShared.

The smart pointer works just like a raw pointer. This means, you can use \\* to dereference them. The regular -> operator works as well:

secondShared->test(); // Calls Foo::test()

Finally, when the last aliased shared_ptr goes out of scope, the destructor of our Foo instance is called.

Warning: Constructing a shared_ptr might throw a bad_alloc exception when extra data for shared ownership semantics needs to be allocated. If the constructor is passed a regular pointer it assumes to own the object pointed to and calls the deleter if an exception is thrown. This means shared_ptr<T>(new T(args)) will not leak a T object if allocation of shared_ptr<T> fails. However, it is advisable to use make_shared<T>(args) or allocate_shared<T>(alloc, args), which enable the implementation to optimize the memory allocation.

Allocating Arrays([]) using shared_ptr

Unfortunately, there is no direct way to allocate Arrays using make_shared<>.

It is possible to create arrays for shared_ptr<> using new and std::default_delete.

For example, to allocate an array of 10 integers, we can write the code as

shared_ptr<int> sh(new int[10], std::default_delete<int[]>());

Specifying std::default_delete is mandatory here to make sure that the allocated memory is correctly cleaned up using delete[].

If we know the size at compile time, we can do it this way:

template<class Arr>
struct shared_array_maker {};
template<class T, std::size_t N>
struct shared_array_maker<T[N]> {
  std::shared_ptr<T> operator()const{
    auto r = std::make_shared<std::array<T,N>>();
    if (!r) return {};
    return {, r};
template<class Arr>
auto make_shared_array()
-> decltype( shared_array_maker<Arr>{}() )
{ return shared_array_maker<Arr>{}(); }

then make_shared_array<int[10]> returns a shared_ptr<int> pointing to 10 ints all default constructed.

With C++17, shared_ptr gained special support for array types. It is no longer necessary to specify the array-deleter explicitly, and the shared pointer can be dereferenced using the [] array index operator: