【问题标题】:Why to use std::move despite the parameter is an r-value reference尽管参数是 r 值引用,为什么要使用 std::move
【发布时间】:2019-07-23 21:35:46
【问题描述】:

我对在下面的代码中使用std::move() 感到困惑:

如果我在 (2) 处取消注释行,输出将是:1 2 3 但如果我在 (1) 处取消注释行,输出将什么都不是,这意味着 std::vector 的移动构造函数被调用!

为什么我们必须在 (1) 处再次调用 std::move 才能调用 std::vector 的移动构造函数?

我的理解是std::move得到了它的参数r-value,那么为什么我们必须在(1)处得到r-valuer-value呢?

我认为 (2) 处的这条线 _v = rv; 更合乎逻辑,应该使 std::vector 移动构造函数在没有 std::move 的情况下被调用,因为 rv 本身首先是 r-value 引用。

template <class T>
class A
{
public:
    void set(std::vector<T> & lv)
    {

    }  
    void set(std::vector<T> && rv)
    {           
        //_v = std::move(rv);          (1)
        //_v = rv;                     (2)
    }

private:
    std::vector<T> _v;
};

int main()
{
    std::vector<int> vec{1,2,3};
    A<int> a;

    a.set(std::move(vec));
    for(auto &item : vec)
        cout << item << " ";
    cout << endl;

    return 0;
}

【问题讨论】:

    标签: c++ c++11 c++14 move stdmove


    【解决方案1】:

    每个命名对象都是左值ref about Lvalue:

    变量、函数、模板参数对象的名称(因为 C++20) 或数据成员,无论类型如何,例如 std::cin 或 标准::endl。 即使变量的类型是右值引用, 由其名称组成的表达式是左值表达式;

    vector 有两个赋值运算符重载,一个用于左值引用,另一个用于右值引用。

    vector::operator=(const vector&) // copy assignment operator
    vector::operator=(vector&&) // move assignment operator
    

    当 Lvalue 作为 operator= 的参数传递时,将调用采用 Lvalue 引用的重载。 Details here

    当函数同时具有右值引用和左值引用时 重载,右值引用重载绑定到右值(包括 prvalues 和 xvalues),而左值引用重载绑定 到左值

    通过std::move(rv);,您将rv - Lvalue 转换为Rvalue 引用,并调用采用Rvalue 引用的operator=。否则,左值绑定到左值引用,向量被复制而不是被移动。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-05-10
      • 2012-07-28
      • 2020-12-23
      • 2017-06-11
      • 2014-02-16
      • 2018-04-17
      • 1970-01-01
      相关资源
      最近更新 更多