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.

Example: Basic Usage of shared_ptr
#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));
Using std::make_shared (Recommended)
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
| Function | Description |
|---|---|
| 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
#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
#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.