Last Updated: January 3, 2026
When we talk about smart pointers, unique_ptr often takes center stage due to its simplicity and efficiency.
Let’s dive into its core features, use cases, and practical applications.
At its heart, a unique_ptr is a smart pointer that represents sole ownership of an object. When you use unique_ptr, you ensure that there is exactly one pointer managing a resource.
This means that the resource will be automatically freed when the unique_ptr goes out of scope, reducing the chances of memory leaks.
Creating a unique_ptr is straightforward, and the preferred method is using std::make_unique. This function not only simplifies the syntax but also minimizes the risk of memory leaks that can occur with raw pointers. Here’s how you can create a unique_ptr:
Always prefer std::make_unique over direct new statements when creating unique_ptr. It’s safer and cleaner.
The unique_ptr takes ownership of the resource, and it will automatically clean up when it goes out of scope.
One of the most powerful features of unique_ptr is its ability to transfer ownership. You can’t copy a unique_ptr because ownership should not be duplicated, but you can move it. This is done using std::move, which transfers ownership from one unique_ptr to another.
Here’s an example to illustrate this:
In this case, ptr1 transfers ownership of the Sample object to the process function. After the move, ptr1 becomes null, preventing potential double deletion.
Sometimes, you might need more control over how a resource is released. This is where custom deleters come into play. A unique_ptr allows you to specify a custom deleter, which can be especially useful for managing resources that require specific cleanup procedures.
Here’s how you can use a custom deleter:
In this example, CustomDeleter defines how to delete an int. The unique_ptr uses this deleter instead of the default delete, allowing for more flexible resource management.
Be careful with custom deleters, especially if they reference other resources or if they require additional cleanup steps that could lead to undefined behavior.
Despite its benefits, unique_ptr is not without its challenges. Here are some common pitfalls to be aware of:
unique_ptr cannot be copied. Attempting to copy will result in a compilation error. Always use std::move when transferring ownership.unique_ptr with a non-heap allocated resource (like a stack variable), it can lead to problems.unique_ptr. Use get() to retrieve the raw pointer, but remember that this temporarily relinquishes ownership.If you need to pass a unique_ptr to a function, consider passing it by reference to avoid transferring ownership unless that's your intention.
unique_ptr is widely used in scenarios where resource management is critical. Here are a few common use cases:
unique_ptr to manage dynamically allocated members within a class, ensuring proper cleanup when the object is destroyed.unique_ptr allows for safe ownership transfer while preventing memory leaks.unique_ptr can be used to manage child nodes, ensuring that the entire structure is cleaned up.Now that you have a solid grasp of unique_ptr and how it handles unique ownership of resources, you're ready to explore shared_ptr.
In the next chapter, we will discuss how shared_ptr allows multiple pointers to share ownership of the same resource, delving into its use cases and intricacies.