AlgoMaster Logo

shared ptr

Last Updated: January 3, 2026

6 min read

When managing memory in C++, avoiding leaks and ensuring proper resource management can feel like walking a tightrope.

Enter shared_ptr: a smart pointer that not only simplifies memory management but also allows multiple owners for a single resource. This shared ownership pattern can be invaluable in complex applications, enabling safer interactions with dynamically allocated objects.

In this chapter, we’ll delve into shared_ptr, covering its benefits, functionality, and practical usage.

What is shared_ptr?

At its core, shared_ptr is part of the C++ Standard Library's smart pointer family. It allows multiple pointers to own the same resource. When the last shared_ptr to a resource is destroyed or reset, the resource is automatically freed.

Key Characteristics

  • Reference Counting: Each shared_ptr maintains a reference count, tracking how many shared_ptr instances point to the same object. When you create a new shared_ptr from another, the reference count increases.
  • Automatic Memory Management: You don't need to explicitly delete the resource. Once the reference count reaches zero, the memory is released, preventing memory leaks.
  • Null Safety: Like other smart pointers, shared_ptr can be reset to null safely.

Basic Usage

Here’s how you can create and use a shared_ptr:

In this example, the Resource object is created and owned by res1. When res2 is created, the reference count increases. When res2 goes out of scope, it decrements the count, but the resource remains alive until res1 goes out of scope.

Creating shared_ptr

Creating a shared_ptr can be done in several ways. It’s essential to understand the differences to avoid potential pitfalls.

Using make_shared

The recommended way to create a shared_ptr is by using std::make_shared. This approach is not only cleaner but also more efficient:

Using make_shared has several benefits:

  • Efficiency: It allocates memory for both the object and the control block (which holds the reference count) in a single allocation.
  • Exception Safety: If an exception is thrown during the object's construction, memory is not leaked.

Direct Construction

You can also create a shared_ptr by passing a raw pointer, but this is less safe:

Copying shared_ptr

When you copy a shared_ptr, the reference count increases. Here’s how it works:

Moving shared_ptr

You can also transfer ownership with std::move, which transfers the control of the resource without increasing the reference count:

In this case, res3 takes over the ownership, and res1 no longer points to the resource.

Managing Lifetimes

Understanding how shared_ptr manages lifetimes is crucial for avoiding dangling pointers and leaks.

Circular References

One of the most notorious pitfalls with shared_ptr is creating circular references. If two objects hold shared_ptrs to each other, their reference counts may never reach zero, leading to memory leaks.

Consider this example:

In this case, when createCycle exits, neither node1 nor node2 will be destructed because they are holding references to each other. To avoid this, use weak_ptr for one of the pointers, which we’ll cover in the next chapter.

Custom Deleters

Sometimes, you might need to customize the deletion of the managed object. You can do this by providing a custom deleter:

This approach is useful when you need to perform additional cleanup or manage resources in a specific way.

Real-World Applications

shared_ptr shines in scenarios where resource sharing is necessary, such as in data structures or applications with complex ownership patterns.

Example: Shared Ownership in Trees

In a tree structure where nodes might have multiple parents, shared_ptr is an ideal choice:

In this tree example, we can easily create nodes that are shared among various parts of the tree without worrying about manual memory management.

Example: Resource Management in GUI Applications

In GUI applications, shared resources (like images or configuration data) can be managed using shared_ptr. This way, you can ensure that resources remain available as long as they are needed by any part of the application.

This shared ownership ensures that the image is loaded only once and can be used by different parts of your application without duplicating resources.

Now that you understand shared_ptr, you are ready to explore weak_ptr.

In the next chapter, we will look at how weak_ptr can help prevent circular references and provide a safer way to manage shared resources without increasing reference counts.