std::unique_ptr<int> ptr() {
std::unique_ptr<int> p(new int(3));
return p; // Why doesn't this require explicit move using std::move?
} // Why didn't the data pointed to by 'p' is not destroyed here though p is not moved?
int main() {
std::unique_ptr<int> a = ptr(); // Why doesn't this require std::move?
std::cout << *a; // Prints 3.
}
In the above code, the function ptr()
returns a copy of p
. When p
goes out of scope, the data '3' should get deleted. But how does the code work without any access violation?
Because the unique pointer does not have a copy constructor. Hence you cannot pass it by value, because passing by value requires making a copy. Actually that is nearly the sole and whole point of a unique_ptr .
If a function returns a std::unique_ptr<> , that means the caller takes ownership of the returned object.
A unique_ptr can only be moved. This means that the ownership of the memory resource is transferred to another unique_ptr and the original unique_ptr no longer owns it. We recommend that you restrict an object to one owner, because multiple ownership adds complexity to the program logic.
unique_ptr. An unique_ptr has exclusive ownership of the object it points to and will destroy the object when the pointer goes out of scope.
This is set out in the C++11 standard, § 12.8/32:
When the criteria for elision of a copy operation are met or would be met save for the fact that the source object is a function parameter, and the object to be copied is designated by an lvalue, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue....
(emphasis mine). In plain english, it means that the lvalue p
can be treated as an rvalue
when it comes to overload resolution, because it is a candidate for copy elision. This in turn means the move constructor is picked up on overload resolution (in actual fact, the move copy is probably elided anyway.)
Because return
of certain expressions, such as local automatic variables, are explicitly defined to return a moved object, if the moving operator is available.
So:
return p;
is more or less similar to:
return std::move(p);
But note that this will not work for example with a global variable.
std::unique_ptr<int> g(new int(3));
std::unique_ptr<int> ptr() {
return g; // error!!!
}
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