I know that std::unique_ptr
is used when an object has only one owner and std::shared_ptr
is used when an object has multiple owners. What does it mean to be the unique owner of an object?
Does being the unique owner mean that nobody else gets to see the object?
Can I return the raw pointer using the get()
method when passing the pointer as a reference?
I feel that if I have to use get()
, then I have either transfer ownership by using std::move
, or use a shared pointer.
Ownership means “responsibility to cleanup”. The owner of the memory is the one who has to delete its pointer. Deletion can either be explicit (through the keyword delete of the function free() regarding raw pointers) or bound to the lifetime of an object (through smart pointers and RAII1).
In C++11 we can transfer the ownership of an object to another unique_ptr using std::move() . After the ownership transfer, the smart pointer that ceded the ownership becomes null and get() returns nullptr.
That is, you should know that a unique_ptr will safely delete its underlying raw pointer once it goes out of scope.
A unique_ptr does not share its pointer. It cannot be copied to another unique_ptr , passed by value to a function, or used in any C++ Standard Library algorithm that requires copies to be made. A unique_ptr can only be moved.
Ownership is all about: who cleans up the resource when it is no longer needed?
To be the only owner of a resource means that only you are responsible for deleting the object when it is no longer needed. This implies that nobody else can use the object after your lifetime ended. If others depend on the object still being alive after your lifetime ended you need shared ownership.
In modern C++, raw pointers should not participate in ownership. When you pass a raw pointer to a function you expect that this function will not hold on to this pointer to use it later.
Ownership talks about how is responsible about the lifetime of the object.
Let say you have a class shape
that on which you can do various actions like, calculating the surface area, enlarging or shrinking that object, ...
And those tasks are performed by free functions calculate_shape_area
, enlarge_shape
, shrink_shape
, and you pass the shape to that function, then those functions don't require ownership over that object, they only need to know the object while they are called. So you can (and should) pass that object as raw pointer:
struct shape {};
double calculate_shape_area(shape* obj) {
// calculate the area, obj is only used within that function
// and not stored anywhere else
}
int main() {
auto obj = std::make_unique<shape>();
auto area = calculate_shape_area(obj.get());
}
If you, on the other hand, want to store that shape in a scene graph using insert
and that scenegraph, at a later step, displays all shapes. Then the scenegraph needs to know about that object after the call of insert
so it either needs to create a copy of it or needs to claim ownership over it. And if you don't want to create a copy then you either need to move a unique_ptr
to that insert
or use shared_ptr
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With