Example code:
#include<memory>
#include<iostream>
int main()
{
std::unique_ptr<int> intPtr{new int(3)};
int* myPtr = intPtr.get();
*myPtr = 4;
std::cout<<"New result for intPtr: "<< *intPtr.get()<<std::endl;
}
Doesn't this defeat the whole purpose behind std::unique_ptr
? Why is this allowed?
Edit: I thought the whole purpose behind std::unique_ptr was to have sole ownership of an object. But this example, the object can be modified through another pointer. Doesn't this defeat std::unique_ptr's purpose?
While Smart pointers manage the lifetime of an object being pointed to, it is often still useful to have access to the underlying raw pointer.
In fact if we read Herb Sutter's GotW #91 Solution: Smart Pointer Parameters he recommends passing parameters by pointer or reference when the function is agnostic to the lifetime of the parameter, he says:
Pass by * or & to accept a widget independently of how the caller is managing its lifetime. Most of the time, we don’t want to commit to a lifetime policy in the parameter type, such as requiring the object be held by a specific smart pointer, because this is usually needlessly restrictive.
and we should pass by unique_ptr when the function is a sink:
Passing a unique_ptr by value is only possible by moving the object and its unique ownership from the caller to the callee. Any function like (c) takes ownership of the object away from the caller, and either destroys it or moves it onward to somewhere else.
and finally pass a unique_ptr
by reference when we can potentially modify it to refer to a different object:
This should only be used to accept an in/out unique_ptr, when the function is supposed to actually accept an existing unique_ptr and potentially modify it to refer to a different object. It is a bad way to just accept a widget, because it is restricted to a particular lifetime strategy in the caller.
Of course, we are required to get the underlying pointer if we have to interface with C libraries that take pointers.
In your specific example:
int* myPtr = intPtr.get();
There is no transfer of ownership to another smart pointer so there are no problems as long as you don't attempt to delete
the pointer via myPtr
. You can transfer ownership to another unique_ptr
by moving it:
std::unique_ptr<int> intPtr2( std::move( intPtr ) ) ;
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