I have written two sets of functions, F1/test1 and F2/test2 and I'm trying to understand the differences in the behavior of std::move and the transfer of ownership with std::unique_ptr in these functions. Here is the code:
void F1(std::unique_ptr<Dog>&& uPtr)
{
std::cout << "F1 \n";
}
void test1()
{
std::unique_ptr<Dog> pD(new Dog("Gunner"));
F1(std::move(pD));
if (pD == nullptr)
{
std::cout << "Null\n";
}
std::cout << "Test \n";
}
void F2(std::unique_ptr<Dog> uPtr)
{
std::cout << "F2 \n";
}
void test2()
{
std::unique_ptr<Dog> pD(new Dog("Smokey"));
F2(std::move(pD));
if (pD == nullptr)
{
std::cout << "Null\n";
}
std::cout << "Test \n";
}
In test1, F1 is called with std::move(pD) as the argument, where uPtr is an rvalue reference to std::unique_ptr. After the call to F1, I checked if pD is null. I was expecting that pD would be null because std::move(pD) was used to pass it to F1, but it's not null. Why is this the case?
In test2, F2 is called with std::move(pD) as the argument, where uPtr is a by-value parameter of type std::unique_ptr. After the call to F2, I checked if pD is null. In this case, pD is null. This is as I expected because std::move(pD) was used to pass it to F2, but why is this behavior different from test1?
Any help would be appreciated!
An object is not moved until a call to the move constructor or the move assignment operator is done. std::move
is only a cast operator from an lvalue to an rvalue, no data is actually moved at that point. A better name for std::move
would be std::cast_to_rvalue
but that would be a bit verbose.
For F1
, the pointer is passed by rvalue reference so the function is still using the instance from the caller. Since uPtr
is untouched in the function, the original pointer will still be valid.
For F2
, the pointer is passed by value so the move constructor will have to be called before entering the function to create the new object. Even though the pointer is untouched in the function, the move operation has already taken place so the instance of the caller is affected.