Here are my test class. VTX has both copy assignment and move assignment.
VTZ has a constructor that takes VTS&& to initialize its vtx memeber.
struct VTX
{
int x;
vector<int> vts;
VTX & operator= (const VTX & other)
{
x = other.x;
vts = other.vts;
cout << "copy assignment\n";
return *this;
}
VTX & operator= (VTX && other)
{
x = other.x;
vts = std::move(other.vts);
cout << "move assignment\n";
return *this;
}
};
struct VTZ
{
VTX vtx;
VTZ(VTX && vvv)
{
vtx = vvv;
}
VTZ()
{}
};
Test code:
int main(VOID)
{
VTX vtx;
vtx.vts.resize(10);
VTZ vtz(std::move(vtx));
return 0;
}
I think the move assignment of VTX will be called when VTZ is constructed. But
Output:
copy assignment
I'm really confused why is copy assignment called but not move assignment?
Because vvv is an lvalue expression (even its type is VTX &&). Types and value categories are different things.
The following expressions are lvalue expressions:
- the name of a variable, a function
, a template parameter object (since C++20), or a data member, regardless of type, such asstd::cinorstd::endl. Even if the variable's type is rvalue reference, the expression consisting of its name is an lvalue expression;
You can use std::move to convert it to rvalue (xvalue) expression,
VTZ(VTX && vvv)
{
vtx = std::move(vvv);
}
To put it another way (from the other answer currently here), this line right here:
vtx = vvv;
performs a copy, not a move.
If you want to move, you have to do something like this answer from another question:
VTZ(VTX && vvv) : vtx(std::move(vvv)) {
}
Or, you could do as songyuanyao suggested. Either one will work.
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