std::unique_ptr
is a smart pointer that exclusively owns and manages the object it points to. When a unique_ptr
is destroyed, the object it manages is automatically destroyed as well. A key feature of unique_ptr
is that it cannot be copied, but it can be moved. This is where move semantics come into play.
Consider this example:
#include <iostream>
#include <memory>
class Resource {
public:
Resource() {
std::cout << "Resource acquired\n";
}
~Resource() {
std::cout << "Resource destroyed\n";
}
};
int main() {
std::unique_ptr<Resource> ResA{new Resource{}};
std::unique_ptr<Resource> ResB{std::move(ResA)};
if (!ResA) {
std::cout << "ResA is empty\n";
}
}
Resource acquired
ResA is empty
Resource destroyed
Here, ResA
initially manages a Resource
object. When we move from ResA
to ResB
, ownership of the Resource
is transferred to ResB
. After the move, ResA
is empty (it doesn't manage an object anymore), and ResB
manages the Resource
.
This is possible because unique_ptr
has a move constructor and a move assignment operator. When you use std::move()
on a unique_ptr
, these move operations are invoked to transfer ownership of the managed object.
The move constructor of unique_ptr
looks something like this:
unique_ptr(unique_ptr&& other) noexcept {
ptr = other.ptr;
other.ptr = nullptr;
}
It takes the pointer from other
and sets other
's pointer to nullptr
. This efficiently transfers ownership without any copying.
The move semantics of unique_ptr
are what allow it to be returned from functions and stored in containers like std::vector
, enabling efficient and safe resource management.
It's worth noting that the use of std::move()
with unique_ptr
is not strictly necessary in many cases, as the compiler can infer that a move should happen in certain situations (like returning a local unique_ptr
from a function). However, using std::move()
can make the intention clearer and is necessary in some situations (like moving from a named unique_ptr
as in the example above).
Answers to questions are automatically generated and may not have been reviewed.
Learn how we can improve the performance of our types using move constructors, move assignment operators and std::move()