PSL PSL - 2 months ago 9
C++ Question

Why do I have to call move on an rvalue reference?

In the code below, why doesn't the first call

mkme = mvme_rv
dispatch to
T& operator=(const T&&)
?

#include <iostream>
#include <string>
#include <vector>

using namespace std;
using T = vector<int>;

int main()
{
T mvme(10, 1), mkme;
T&& mvme_rv = move(mvme); // rvalue ref?
mkme = mvme_rv; // calls T& operator=(const T&)?
cout << mvme.empty(); // 0
mkme = move(mvme_rv); // calls T& operator=(const T&&)?
cout << mvme.empty(); // 1
}

Answer

This line of code:

mkme = mvme_rv;

is a copy and will thus use a copy assignment (T& operator=(const T&)). The key thing about this is BOTH objects can be used afterwards and should - if implemented correctly - provide two identical objects.

By contrast, this line of code:

mkme = move(mvme_rv);

is a move assignment (T& operator=(const T&&)). By convention, this will trash the mvme_rv object (or at least clear it) and make mkme basically what mvme_rv was previously.

Effectively T&& means a temporary object (aka xvalue) - something that will not last. The std::move method basically casts the object to a temporary (credit to @richard-Hodges for that wording). This can then be used in the move assignment method.

So finally to answer you question of why doesn't mkme = mvme_rv dispatch to T& operator=(const T&&): it's because mvme_rv isn't a temporary object (aka xavalue).


More about xvalues: http://en.cppreference.com/w/cpp/language/value_category

Comments