C++ 为什么';tc++;默认情况下是否移动构造右值引用?

C++ 为什么';tc++;默认情况下是否移动构造右值引用?,c++,rvalue-reference,move-constructor,lvalue-to-rvalue,stdmove,C++,Rvalue Reference,Move Constructor,Lvalue To Rvalue,Stdmove,假设我有以下功能 void doWork(Widget && param) // param is an LVALUE of RRef type { Widget store = std::move(param); } 为什么需要使用std::move()将param转换回右值?param的类型是右值,因为它在函数签名中声明为右值引用,这难道不应该很明显吗?这里不应该仅根据这个原则自动调用move构造函数吗 为什么默认情况下不会发生这种情况 您的设计: void d

假设我有以下功能

void doWork(Widget && param)  // param is an LVALUE of RRef type
{
    Widget store = std::move(param); 
}
为什么需要使用
std::move()
param
转换回右值?
param
的类型是右值,因为它在函数签名中声明为右值引用,这难道不应该很明显吗?这里不应该仅根据这个原则自动调用move构造函数吗

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

您的设计:

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

语言不能这样设计。

哦,我明白了。这是有道理的!我同意,复制设计总是比隐式移动更安全@barney,当一个简单的例子让你说“哦,我明白了。这很有意义!”很高兴我能提供一个。@bolov,我在想更多的事情,让编译器在任何可能的“移动后使用”操作上抛出一个错误。相反,对于0.1%的情况,你“还不想移动它”。因为基本上,我看到在实际代码中,人们忘记放置
std::move
,而得到一个他们不想要的副本,而不是多次使用。@Fire:“然后,在0.1%的情况下,如果您“还不想移动它”,则使用类似于std::explicit_copy的std::move副本,这将破坏与C++03的向后兼容性。”。