Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the type of std :: move?

This code works as expected (online here). At the end v is empty and w is not empty as it has pilfered the contents of v.

    vector<int> v;
    v.push_back(1);
    cout << "v.size(): " << v.size() << endl;
    auto vp = move(v);
    vector<int> w(vp);
    cout << "w.size(): " << w.size() << endl;
    cout << "v.size(): " << v.size() << endl;

But if I replace auto vp=move(v) with

    vector<int> && vp = move (v);

Then it doesn't move. Instead it copies and both vectors are non-empty at the end. As shown here.

Clarification: More specifically, what is the auto-derived type of vp? If it's not vector<int> &&, then what else could it be? Why do the two examples give different results despite being so similar?

Extra: I also tried this, and it still copied instead of moving

    std :: remove_reference< vector<int> > :: type && vp = move(v);
like image 377
Aaron McDaid Avatar asked Dec 07 '22 17:12

Aaron McDaid


2 Answers

Edit for OP's clarification: the auto-derived type of move(v) is vector<int>. See C++11 "auto" semantics.

The 1st example does this:

move 'v' into 'vp'
copy 'vp' into 'w'

and the 2nd example does this:

set 'vp' as rvalue-reference of 'v'
copy 'vp' (which is 'v') into 'w'

What std:move does is simply casting a type to an rvalue (See What is std::move(), and when should it be used?). Therefore, in

vector<int>&& vp = move(v);

it's just setting the rvalue-reference vp to v and do nothing else. Also, an rvalue-reference is an lvalue (it has a name), so

vector<int> w(vp);

will call the copy constructor to copy vp (which is v) into w.

It will call the move constructor if you make vp an rvalue (Example):

vector<int> w(move(vp))

You may want to read this: C++ Rvalue References Explained.

like image 109
kennytm Avatar answered Dec 26 '22 23:12

kennytm


In the first case:

auto vp = move(v);

is equivalent to:

vector<int> vp = move(v);

This invokes the move constructor, since move(v) has type vector<int>&&, hence vp ends up pilfering the contents of v.

In the second case:

vector<int>&& vp = move(v);

just makes vp an r-value reference to v. This doesn't result in the move constructor or copy constructor being called, and nothing is pilfered.

like image 41
Stuart Golodetz Avatar answered Dec 27 '22 00:12

Stuart Golodetz