【问题标题】:Why doesn't C++ move construct rvalue references by default? [duplicate]为什么 C++ 默认不移动构造右值引用? [复制]
【发布时间】:2018-02-01 07:04:35
【问题描述】:

假设我有以下功能

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

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

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

【问题讨论】:

    标签: c++ rvalue-reference move-constructor lvalue-to-rvalue stdmove


    【解决方案1】:

    你的设计:

    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,我在想更多的是让编译器在任何潜在的“移动后使用”操作上抛出错误。然后将 std::explicit_copystd::move 相反,用于 0.1% 的情况下您“还不想移动它”。
    • 因为基本上,我在实际代码中看到人们忘记输入std::move 并获得他们不想要的副本,而不是多次使用。
    • @Fire: “然后有一个 std::explicit_copy 就像 std::move 的对立面一样,对于 0.1% 你“还不想移动它”的情况。”这会破坏对 C++03 的向后兼容性。
    猜你喜欢
    • 2010-10-25
    • 1970-01-01
    • 1970-01-01
    • 2011-04-17
    • 2013-08-11
    • 2013-03-16
    • 1970-01-01
    • 1970-01-01
    • 2020-05-08
    相关资源
    最近更新 更多