13

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

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

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

我的理解是std::move获取r-value它的参数,为什么我们必须在(1)处 r-value获取?r-value

我认为_v = rv;(2)处的这一行更合乎逻辑,应该使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;
}
4

1 回答 1

11

每个命名对象都是关于 Lvalue 的 Lvalue ref

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

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

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

当 Lvalue 作为 的参数传递时,将调用采用 Lvalue 引用的重载operator=详情在这里

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

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

于 2019-03-01T20:30:31.460 回答