shared_ptr in C++

Last Updated : 21 Jul, 2026

std::shared_ptr is a smart pointer introduced in C++11 that enables multiple pointers to share ownership of the same dynamically allocated object. It uses reference counting to automatically manage the object's lifetime.

  • Supports shared ownership of objects.
  • Uses reference counting for automatic memory management.
  • Eliminates manual memory deallocation.
shared_ptr-in-CPP

Example: Basic Usage of shared_ptr

C++
#include <iostream>
#include <memory>
using namespace std;

class A {
public:
    void show() { cout << "A::show()" << endl; }
};

int main()
{
    // Creating a shared pointer and accessing the object
    shared_ptr<A> p1(new A);
    // Printing the address of the managed object
    cout << p1.get() << endl;
    p1->show();
  
    // Creating a new shared pointer that shares ownership
    shared_ptr<A> p2(p1);
    p2->show();
  
    // Printing addresses of p1 and p2
    cout << p1.get() << endl;
    cout << p2.get() << endl;
  
    // Returns the number of shared_ptr objects
    // referring to the same managed object
    cout << p1.use_count() << endl;
    cout << p2.use_count() << endl;
  
    // Relinquishes ownership of p1 on the object
    // and pointer becomes NULL
    p1.reset();
    cout << p1.get() << endl; // This will print nullptr or 0
    cout << p2.use_count() << endl;
    cout << p2.get() << endl;

    /*
    These lines demonstrate that p1 no longer manages an
    object (get() returns nullptr), but p2 still manages the
    same object, so its reference count is 1.
    */
    return 0;
}

Output
0x416eb0
A::show()
A::show()
0x416eb0
0x416eb0
2
2
0
1
0x416eb0

Explanation

  • p1 initially owns the object, and p2 shares ownership with it, increasing the reference count to 2.
  • p1.reset() releases its ownership, but the object remains alive because p2 still owns it.

Syntax

std::shared_ptr<T> ptr;

Creating std::shared_ptr

std::shared_ptr objects can be created in two ways:

Using new

std::shared_ptr<int> ptr(new int(10));

std::shared_ptr<int> ptr = std::make_shared<int>(10);

std::make_shared() is preferred because it performs a single memory allocation and improves performance.

Working of std::shared_ptr

When multiple shared pointers refer to the same object:

  • Copying a shared_ptr increases the reference count.
  • Destroying or resetting a shared_ptr decreases the reference count.
  • The managed object is destroyed automatically when the reference count reaches zero.

Common Member Functions

FunctionDescription
use_count()Returns the current reference count
reset()Releases ownership of the object
get()Returns the raw pointer
unique()Checks whether only one owner exists
swap()Swaps ownership with another shared pointer

Example: Using std::make_shared

C++
#include <iostream>
#include <memory>
using namespace std;

int main()
{
    // Creating shared pointers using std::make_shared
    shared_ptr<int> shr_ptr1 = make_shared<int>(42);
    shared_ptr<int> shr_ptr2 = make_shared<int>(24);
    // Accessing the values using the dereference operator
    // (*)
    cout << "Value 1: " << *shr_ptr1 << endl;
    cout << "Value 2: " << *shr_ptr2 << endl;
    // Using the assignment operator (=) to share ownership
    shared_ptr<int> shr_ptr3 = shr_ptr1;
    // Checking if shared pointer 1 and shared pointer 3
    // point to the same object
    if (shr_ptr1 == shr_ptr3) {
        cout << "shared pointer 1 and shared pointer 3 "
                "point to the same object."
             << endl;
    }
    // Swapping the contents of shared pointer 2 and shared
    // pointer 3
    shr_ptr2.swap(shr_ptr3);
    // Checking the values after the swap
    cout << "Value 2 (after swap): " << *shr_ptr2 << endl;
    cout << "Value 3 (after swap): " << *shr_ptr3 << endl;
    // Using logical operators to check if shared pointers
    // are valid
    if (shr_ptr1 && shr_ptr2) {
        cout << "Both shared pointer 1 and shared pointer "
                "2 are valid."
             << endl;
    }
    // Resetting a shared pointer
    shr_ptr1.reset();
}

Output
Value 1: 42
Value 2: 24
shared pointer 1 and shared pointer 3 point to the same object.
Value 2 (after swap): 42
Value 3 (after swap): 24
Both shared pointer 1 and shared pointer 2 are valid.

Explanation

  • std::make_shared() efficiently creates and initializes the object, while shr_ptr3 shares ownership with shr_ptr1.
  • swap() exchanges ownership between pointers, and reset() releases ownership of the managed object.

Example: Implementing a Linked List Using std::shared_ptr

C++
#include <iostream>
#include <memory>
using namespace std;

// Define a singly linked list node
struct Node {
    int data;
    shared_ptr<Node> next;

    Node(int val)
        : data(val), next(nullptr) {}
};

class LinkedList {
public:
    LinkedList()
        : head(nullptr), tail(nullptr) {}

    // Insert a new node at the end of the linked list
    void insert(int val)
    {
        shared_ptr<Node> newNode = make_shared<Node>(val);

        if (!head) {
            head = tail = newNode;
        } else {
            tail->next = newNode;
            tail = newNode;
        }
    }

    // Delete a node with a given value
    void del(int val)
    {
        if (!head)
            return;

        if (head->data == val) {
            head = head->next;

            if (!head)
                tail = nullptr;

            return;
        }

        shared_ptr<Node> current = head;

        while (current->next && current->next->data != val) {
            current = current->next;
        }

        if (current->next) {

            if (current->next == tail)
                tail = current;

            current->next = current->next->next;
        }
    }

    // Print the linked list
    void Print()
    {
        shared_ptr<Node> current = head;

        while (current) {
            cout << current->data << " -> ";
            current = current->next;
        }

        cout << "NULL" << endl;
    }

private:
    shared_ptr<Node> head;
    shared_ptr<Node> tail;
};

int main()
{
    LinkedList linkedList;

    linkedList.insert(1);
    linkedList.insert(2);
    linkedList.insert(3);

    cout << "Linked List: ";
    linkedList.Print();

    linkedList.del(2);

    cout << "Linked List after deleting 2: ";
    linkedList.Print();

    return 0;
}

Output
Linked List: 1 -> 2 -> 3 -> NULL
Linked List after deleting 2: 1 -> 3 -> NULL

Explanation

  • A shared_ptr is used to automatically manage the lifetime of each node.
  • A tail pointer allows inserting new nodes at the end in O(1) time.
  • Nodes are automatically destroyed when no shared_ptr references them, so manual delete is not required.

Benefits of Using std::shared_ptr

std::shared_ptr is particularly useful when multiple parts of a program need to access and share ownership of the same resource.

  • Simplifies shared resource management.
  • Prevents memory leaks caused by forgotten delete operations.
  • Works seamlessly with STL containers and algorithms.
  • Supports automatic object lifetime management.

Limitations of std::shared_ptr

Although useful, std::shared_ptr introduces some overhead.

  • Reference counting incurs additional runtime cost.
  • Requires extra memory for the control block.
  • Circular references can cause memory leaks.
  • Slower than std::unique_ptr due to ownership tracking.
Comment