std::unique_ptr
std::unique_ptr in C++: An Overview
std::unique_ptr in C++: An Overviewstd::unique_ptr is a smart pointer introduced in C++11 that provides automatic and exclusive ownership of a dynamically allocated object. It resides in the <memory> header and is part of the Standard Template Library (STL). Below is a comprehensive explanation of what std::unique_ptr is, what it does, and its features.
Purpose of std::unique_ptr
std::unique_ptrAutomatic Memory Management:
std::unique_ptrmanages the lifetime of a dynamically allocated object. When thestd::unique_ptrgoes out of scope, the object it owns is automatically deleted.Exclusive Ownership: A
std::unique_ptrowns the object exclusively. No otherstd::unique_ptrcan own the same object unless ownership is explicitly transferred.
Key Features of std::unique_ptr
std::unique_ptr1. Exclusive Ownership
A
std::unique_ptrcan only point to one dynamically allocated object at a time.It cannot be copied, but ownership can be transferred using
std::move.
std::unique_ptr<int> ptr1 = std::make_unique<int>(42);
// std::unique_ptr<int> ptr2 = ptr1; // Error: copy not allowed
std::unique_ptr<int> ptr2 = std::move(ptr1); // Ownership transferred2. Automatic Deletion
When the
std::unique_ptris destroyed or reassigned, it automatically deletes the object it owns.This helps prevent memory leaks, as you don't need to explicitly
deletethe object.
{
std::unique_ptr<int> ptr = std::make_unique<int>(42);
// The integer will be automatically deleted when 'ptr' goes out of scope.
}3. Null State
A
std::unique_ptrcan be null, indicating that it doesn’t own any object. This is the default state after initialization or ownership transfer.
std::unique_ptr<int> ptr;
if (!ptr) {
std::cout << "ptr is null." << std::endl;
}4. Custom Deleters
std::unique_ptrsupports custom deleters for specialized cleanup. You can specify a callable object (like a function pointer or lambda) to define how the object should be deleted.
struct CustomDeleter {
void operator()(int* p) const {
std::cout << "Deleting " << *p << std::endl;
delete p;
}
};
std::unique_ptr<int, CustomDeleter> ptr(new int(42));5. Compatibility with Arrays
A specialization of
std::unique_ptr(std::unique_ptr<T[]>) is available to manage dynamic arrays.
std::unique_ptr<int[]> arr = std::make_unique<int[]>(5);
for (int i = 0; i < 5; ++i) arr[i] = i;6. Non-Copyable, Move-Only
Copying a
std::unique_ptris prohibited, enforcing the single-ownership principle.Ownership can be transferred using
std::move.
std::unique_ptr<int> ptr1 = std::make_unique<int>(10);
std::unique_ptr<int> ptr2 = std::move(ptr1); // Ownership transferred7. Lightweight
Since
std::unique_ptrdoes not use reference counting (unlikestd::shared_ptr), it is lightweight and incurs minimal overhead.
8. Efficient Memory Allocation
Using
std::make_unique(introduced in C++14), you can create astd::unique_ptrwith a single allocation. This is safer and more efficient than creating an object withnew.
auto ptr = std::make_unique<int>(42);Common Use Cases
Managing Resources in RAII (Resource Acquisition Is Initialization):
std::unique_ptrensures that resources are cleaned up when no longer needed.Preventing Memory Leaks: Eliminates the need for manual
deletecalls.Dynamic Object Ownership Transfer: Allows controlled transfer of ownership between different parts of the program.
Using with Polymorphic Objects: Enables managing polymorphic objects without worrying about deleting derived types correctly.
struct Base { virtual ~Base() = default; };
struct Derived : Base {};
std::unique_ptr<Base> ptr = std::make_unique<Derived>();Methods and Operations
Constructor
Default:
std::unique_ptr<T>()Null pointer:
std::unique_ptr<T>(nullptr)Take ownership:
std::unique_ptr<T>(T* ptr)
Modifiers
release(): Releases ownership of the object and returns the raw pointer.reset(): Deletes the currently owned object and optionally takes ownership of another.swap(): Exchanges ownership with anotherstd::unique_ptr.
Accessors
get(): Returns the raw pointer without releasing ownership.operator*: Dereferences the stored pointer.operator->: Accesses members of the stored object.
Limitations
Not Copyable: You cannot pass
std::unique_ptrby value.Ownership Responsibility: Requires careful ownership management when transferring with
std::move.
Comparison with Other Smart Pointers
std::shared_ptr:Allows shared ownership.
Uses reference counting, which introduces overhead.
std::weak_ptr:Non-owning reference to a
std::shared_ptrobject.
std::unique_ptr is more lightweight and ensures strict ownership compared to std::shared_ptr.
Code Example: Comprehensive Usage
#include <iostream>
#include <memory>
struct Resource {
Resource() { std::cout << "Resource acquired\n"; }
~Resource() { std::cout << "Resource destroyed\n"; }
void sayHello() const { std::cout << "Hello from Resource\n"; }
};
void useResource(std::unique_ptr<Resource> res) {
res->sayHello();
// Resource will be destroyed when function exits.
}
int main() {
auto res = std::make_unique<Resource>();
useResource(std::move(res)); // Transfer ownership
if (!res) {
std::cout << "Resource ownership transferred\n";
}
// Array example
auto arr = std::make_unique<int[]>(5);
for (int i = 0; i < 5; ++i) arr[i] = i;
for (int i = 0; i < 5; ++i) std::cout << arr[i] << " ";
std::cout << std::endl;
return 0;
}Conclusion
std::unique_ptr is a powerful tool for managing dynamic memory in modern C++. Its single-ownership model ensures safe and efficient resource management, making it an essential component of modern C++ programming.
Last updated