16

I am confused about using std::move() in below code:

If I uncomment line at (2) the output would be: 1 2 3 but if I uncomment line at (1) output would be nothing which means that move constructor of std::vector was called!

Why do we have to make another call to std::move at (1) to make move constructor of std::vector to be called?

What I understood that std::move get the r-value of its parameter so, why we have to get the r-value of r-value at (1)?

I think this line _v = rv; at (2) is more logical and should make std::vector move constructor to be called without std::movebecause rv itself is r-value reference in the first place.

template <class T>
class A
{
public:
    void set(std::vector<T> & lv)
    {

    }  
    void set(std::vector<T> && rv)
    {           
        //_v = std::move(rv);          (1)
        //_v = rv;                     (2)
    }

private:
    std::vector<T> _v;
};

int main()
{
    std::vector<int> vec{1,2,3};
    A<int> a;

    a.set(std::move(vec));
    for(auto &item : vec)
        cout << item << " ";
    cout << endl;

    return 0;
}
Ajay
  • 18,086
  • 12
  • 59
  • 105
Islam Abdeen
  • 539
  • 3
  • 10

1 Answers1

11

Every named object is a Lvalue:

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;

vector has two overloads of assignment operator, one for Lvalue reference and another for Rvalue reference.

vector::operator=(const vector&) // copy assignment operator
vector::operator=(vector&&) // move assignment operator

Overload which takes Lvalue reference is called when Lvalue is passed as argument for operator=. Details here

when a function has both rvalue reference and lvalue reference overloads, the rvalue reference overload binds to rvalues (including both prvalues and xvalues), while the lvalue reference overload binds to lvalues

By std::move(rv); you cast rv - Lvalue to Rvalue reference, and operator= which takes Rvalue reference is called. Otherwise, Lvalue binds to Lvalue reference and vector is copied instead of being moved.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
rafix07
  • 20,001
  • 3
  • 20
  • 33