std::unique_ptr is a smart pointer introduced in C++11 that manages the lifetime of a dynamically allocated object. It automatically releases the associated memory when the pointer goes out of scope, helping prevent memory leaks.
- Manages dynamically allocated objects with exclusive ownership.
- Eliminates the need to manually call delete.
A unique_ptr can be created using the constructor or, preferably, the std::make_unique() function.
#include <iostream>
#include <memory>
using namespace std;
struct A {
void print() {
cout << "Object of A" << endl;
}
};
int main() {
unique_ptr<A> ptr = make_unique<A>();
ptr->print();
cout << "Address: " << ptr.get();
return 0;
}
Output
Object of A Address: 0x416eb0
Explanation
- make_unique<A>() creates an object of type A, and ptr becomes its exclusive owner.
- get() returns the raw pointer without transferring ownership, and the object is automatically destroyed when ptr goes out of scope.
Syntax
std::unique_ptr<Type> ptr(new Type);
or (recommended since C++14)
std::unique_ptr<Type> ptr = std::make_unique<Type>();
std::make_unique() is preferred because it is safer, more concise, and avoids unnecessary memory allocation issues.
Copying a unique_ptr
A unique_ptr cannot be copied because only one pointer can own an object at a time.
#include <iostream>
#include <memory>
using namespace std;
struct A {
void printA() {
cout << "A struct...." << endl;
}
};
int main() {
unique_ptr<A> p1(new A);
p1->printA();
// displays address of the
// containing pointer
cout << p1.get() << endl;
// will give compile time error
unique_ptr<A> p2 = p1;
p2->printA();
return 0;
}
Output
main.cpp: In function ‘int main()’:
main.cpp:18:24: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&)
Explanation
- Copy construction is disabled.
- Allowing multiple owners would defeat the purpose of exclusive ownership.
Moving a unique_ptr
Ownership can be transferred using std::move().
#include <iostream>
#include <memory>
using namespace std;
struct A {
void print() {
cout << "Object of A" << endl;
}
};
int main() {
unique_ptr<A> p1 = make_unique<A>();
unique_ptr<A> p2 = move(p1);
cout << "p1: " << p1.get() << endl;
cout << "p2: " << p2.get() << endl;
p2->print();
return 0;
}
Output
p1: 0 p2: 0x416eb0 Object of A
Explanation
- std::move() transfers ownership from p1 to p2.
- After the transfer, p1 becomes nullptr.
- p2 is now the sole owner of the object.
Common Member Functions of std::unique_ptr
The std::unique_ptr class provides several member functions to access, transfer, release, and manage the owned object.
| Member Function | Description |
|---|---|
| get() | Returns the raw pointer without transferring ownership. |
| release() | Releases ownership and returns the raw pointer. The caller becomes responsible for deleting it. |
| reset() | Replaces the managed object or deletes the current object if no new pointer is provided. |
| swap() | Exchanges the managed objects between two unique_ptr objects. |
| operator* | Dereferences the managed object. |
| operator-> | Accesses members of the managed object. |
| operator bool | Checks whether the unique_ptr currently owns an object. |
Advantages of unique_ptr
The std::unique_ptr provides several benefits for managing dynamically allocated objects safely.
- Ensures exclusive ownership so that only one pointer manages a resource at a time.
- Supports move semantics, allowing safe and efficient transfer of ownership.
- Eliminates the need for manual delete, making code cleaner and less error-prone.
- Provides performance close to raw pointers while offering automatic resource management.
Limitations of unique_ptr
Although std::unique_ptr is useful in many situations, it also has some limitations.
- Does not allow copying because exclusive ownership must always be maintained.
- Cannot be shared between multiple owners; use std::shared_ptr when shared ownership is required.
- Ownership transfer requires explicit use of std::move(), which may be confusing for beginners.
- Managing arrays or custom deletion logic may require a custom deleter or specialized syntax.