Why doesn't C++ move construct rvalue references by default? [duplicate]

Solution 1:

with your design:

void doWork(Widget && param)
{
    Widget store1 = param;     // automatically move param
    Widget store2 = param;     // boom

    Widget store_last = param; // boom    
}

with current design:

void doWork(Widget && param)
{
    Widget store1 = param;                // ok, copy
    Widget store2 = param;                // ok, copy

    Widget store_last = std::move(param); // ok, param is moved at its last use
}

So the moral here is that even if you have an rvalue reference you have a name for it which means you can use it multiple times. As such you can't automatically move it because you could need it for a later use.


Now let's say you want to re-design the language so that the last use is automatically treated as an rvalue.

This can be easily done in the above example:

void doWork(Widget && param)
{
    Widget store1 = param;     // `param` treated as lvalue here, copy
    Widget store2 = param;     // `param` treated as lvalue here, copy

    Widget store_last = param; // `param` treated as rvalue here, move    
}

Let's ignore the inconsistency of how param is treated (which in itself is a problem).

Now think what use of param is the last use:

void doWork(Widget && param)
{  
    Widget store2 = param;        // this can be last use or not

    while (some_condition())
    {
         Widget store1 = param;   // this can be both last use and not
    }
}

The language simply cannot be designed this way.