【问题标题】:How rvalue parameter works?右值参数如何工作?
【发布时间】:2013-05-24 02:41:23
【问题描述】:

所以我真的很惊讶在这段代码中发现了这一点:

void AddLayer( shared_Layer_ptr && pNewLayer_p ){

        m_layers.push_back( pNewLayer_p ); // *
    }

被调用的 push_back 是“& param”,而不是“&& param”版本。 m_layers 是一个 std::vector。 由于 pNewLayer_p 是一个“&&”,我虽然它是一个该死的右值。我设法调用 push_back("&& param") 的唯一方法是使用 std::move:

m_layers.push_back( std::move(pNewLayer_p) );

对我来说似乎是多余的,因为 pNewLayer_p 已经是一个“&&”。我肯定错过了什么,它是什么?

【问题讨论】:

    标签: c++ move semantics


    【解决方案1】:

    pNewLayer_p 是一个右值引用,但它本身不是一个右值——主要是因为它有一个名称。标准中的右值定义如下:

    (3.10/1) 右值(历史上称为右值,因为右值可能出现在赋值表达式的右侧)是 xvalue、临时对象 (12.2) 或其子对象,或者是不与对象关联。

    换句话说,右值是字面量、临时值和其他未命名的对象(例如 xvalues,即刚刚由函数返回但尚未分配给任何东西的值)。

    代码中的右值引用pNewLayer_p 是一个命名对象,因此它本身就是一个左值。将std::move 应用于它,它正式地是一个函数,将它(正式地)变成从函数返回的东西,即一个xvalue,它是一个右值,您可以将它传递给push_back 的移动版本。这就是 std::move 存在的目的。

    (注意:以上假设shared_Layer_ptr是一个类型,而不是模板参数。如果是模板参数,shared_Layer_ptr &&就是所谓的通用引用,即它可能是一个左值引用,也可能是一个右值引用取决于模板的实例化方式。在这种情况下,std::forward 将是合适的函数,而不是 std::move。)

    【讨论】:

    • 在这种情况下使用 std::move 是否值得?它会避免 push_back 上的副本还是完全取决于类型(在本例中为共享 ptr)移动分配重载? (我无法真正理解 Visual Studio 上凌乱的实现)
    • @Icebone1000 如果你使用std::move,它会调用shared_Layer_ptr的move-constructor将其放入vector中。如果你不使用std::move,它将使用复制构造函数。如果shared_Layer_ptr 以类似于std::shared_ptr 的方式工作,则可以预期移动方法要快得多,因为不需要更新引用计数等。 (注意可能还有第三种方法,使用emplace_back而不是push_back。这只能在pNewLayer_p是函数调用时新创建的对象时使用。
    • @Icebone1000 (..cont'd) emplace_back 将构造函数调用的参数用于新的shared_Layer_ptr,而不是构造对象本身。然后它在向量内部构造它。这是最快的,但它只适用于新创建的对象。如果对象是预先存在的并且您想将它们移入,请使用std::move 方法。
    • 谢谢你! shared_Layer_ptr 实际上是一个 std::shared_ptr typedef。我有一种将 std::move 放在我的代码中的冲动
    • @Icebone1000 是的,在上述情况下,我认为它应该有所帮助。如果你想确定的话,一定要测量时间。相关问题:stackoverflow.com/questions/10953325/…
    【解决方案2】:

    想想如果它移动会发生什么pNewLayer

    void AddLayer( shared_Layer_ptr && pNewLayer_p ){
        m_layers.push_back( pNewLayer_p );
        // what if pNewLayer_p is already moved
        another_m_layers.push_back( pNewLayer_p );
    }
    

    因此您必须明确使用std::move

    void AddLayer( shared_Layer_ptr && pNewLayer_p ){
        m_layers.push_back( pNewLayer_p );
        another_m_layers.push_back( std::move(pNewLayer_p) );
    }
    

    如果一个右值引用在一个函数中只能出现一次,那肯定会削弱 C++ 的一些力量。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-24
      • 2013-04-28
      • 1970-01-01
      • 1970-01-01
      • 2021-08-05
      • 1970-01-01
      • 1970-01-01
      • 2018-09-09
      相关资源
      最近更新 更多