Given the class definition:
struct MoveOnly
{
MoveOnly(int v_)
: v(v_)
{
std::cout << ((void*)this) << " MoveOnly " << v << "\n";
}
~MoveOnly()
{
std::cout << ((void*)this) << " ~MoveOnly " << v << "\n";
}
MoveOnly(const MoveOnly&) = delete;
MoveOnly& operator=(const MoveOnly&) = delete;
MoveOnly(MoveOnly &&src)
{
v = std::exchange(src.v, -1);
std::cout << ((void*)this) << " MoveOnly&& " << v << "\n";
}
MoveOnly& operator=(MoveOnly&&) = default;
MoveOnly&& Apply()
{
std::cout << ((void*)this) << " Apply " << v << "\n";
return std::move(*this);
}
int v;
};
The console shows for code:
auto m1 = MoveOnly(1);
m1.Apply();
> 0x7fff5fbff798 MoveOnly 1
> 0x7fff5fbff798 Apply 1
> 0x7fff5fbff798 ~MoveOnly 1
Now, if I change Apply
to return a value instead of an r-value reference:
MoveOnly Apply()
{
std::cout << ((void*)this) << " Apply " << v << "\n";
return std::move(*this);
}
I see:
auto m1 = MoveOnly(1);
m1.Apply();
> 0x7fff5fbff798 MoveOnly 1
> 0x7fff5fbff798 Apply 1
> 0x7fff5fbff790 MoveOnly&& 1
> 0x7fff5fbff790 ~MoveOnly 1
> 0x7fff5fbff798 ~MoveOnly -1
The first example seems to preserve the original object, which goes against my intuition for what std::move does. Although since it doesn't invoke the move constructor, I can see how the original object would still have a 1
.
What I'm trying to figure out here is how the C++ standard explains this behavior and what the uses cases for the different version of Apply()
might be.
Aucun commentaire:
Enregistrer un commentaire