3

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?

Paler
  • 339
  • 4
  • 16

3 Answers3

4

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 as std::cin or std::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);
}
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
1

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.

0

References are an illusion!

Although your parameter is declared VTX&& vvv, inside the VTZ constructor the actual expression vvv is an lvalue VTX.

The reference type doesn't actually persist.

If you want to keep moving the object along, that's fine, but you'll need to write std::move again.

Asteroids With Wings
  • 17,071
  • 2
  • 21
  • 35