为什么 C++ 默认不移动构造右值引用?

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

假设我有以下功能

void doWork(Widget && param)  // param is an LVALUE of RRef type
{
    Widget store = std::move(param); 
}

为什么我需要用 std::move()param 转换回右值? param 的类型是右值,因为它在函数签名中被声明为右值引用,难道不应该很明显吗?仅仅根据这个原则,这里不应该自动调用移动构造函数吗?

为什么默认情况下不发生这种情况?

你的设计:

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

    Widget store_last = param; // boom    
}

当前设计:

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
}

所以这里的寓意是,即使您有一个右值引用,您也有一个名称,这意味着您可以多次使用它。因此,您不能自动移动它,因为您以后可能需要它。


现在假设您想重新设计语言,以便最后一次使用自动被视为右值。

这在上面的例子中很容易做到:

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    
}

让我们忽略 param 处理方式的不一致(这本身就是一个问题)。

现在想想param最后的用途是什么:

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
    }
}

语言根本不能这样设计。