r值参考如何在此处传递?

时间:2019-06-01 07:07:20

标签: c++

void test(vector<int> v) {
    for(int i:v) cout<< i<<" ";
}
int main()
{
    vector<int> v{ 1,2,3 };
    test(move(v));
    cout << "v is gone...."; 
}

我是移动语义和右值引用的新手。在上面的代码中,将打印矢量。显然,此举行之有效。

我不明白它是如何工作的。为什么我不必定义一个接受右值引用的函数?我最好的猜测是编译器会自动生成此代码:

void test(vector<int>&& v) {
    for(int i:v) cout<< i<<" ";
}

2 个答案:

答案 0 :(得分:2)

  

我最好的猜测是编译器会自动生成

编译器将自动生成的唯一代码是针对构造函数,赋值运算符和析构函数的。那些有警告。这里发生的事情与自动生成的代码无关。当您编写test(move(v))(对于某些类型的V)时,可以通过两种方式使它起作用。

  1. test接受类型为V&&的参数。它将很高兴地绑定到您提供的右值引用。
  2. test接受类型为V const&的参数。 const lvlaue引用也绑定到右值引用参数。这样,未针对移动语义进行调整的旧代码仍然可以工作。 const lvlaue参考是一个方便的后备。
  3. test接受V。这里的情况(1)和(2)可以应用于V的构造函数。

在我们的特定情况下,std::vector有一个move构造函数准备接受您提供的引用。

答案 1 :(得分:1)

您可以创建一个带有r值引用的向量:

std::vector<int> a = {1, 2, 3};

std::vector<int> b = std::move(a); // Constructs b from r-value reference

这将调用std::vector的move构造函数,该构造函数基本上只是将数据指针从第一个向量复制到第二个向量。

在示例中调用函数void test(std::vector<int> v)时,会发生相同的事情:编译器调用std::vector的move构造函数,并在为参数{{ 1}}。没有隐式生成任何函数。

v void test(std::vector<int> v)之间的区别。

在第一种情况下,您要按值传递向量。这意味着无论何时调用void test(std::vector<int>&& v),调用test之前,调用函数test都会为堆栈上的新向量分配空间。它必须调用test的构造函数,在此过程中,它要么

  • 移动向量;
  • 复制向量;或
  • 神奇地就地构建矢量(如果您在调用std::vector的站点(例如在test中构建矢量),就会发生这种情况

另一方面,test(std::vector<int>{1, 2, 3})通过引用接受参数。这意味着,当您通过移动变量来调用此版本的test(std::vector<int>&& v)时,不会创建新矢量。您提供的任何矢量都会通过引用传递,结果 test对矢量所做的任何更改都会显示在原始矢量上。

例如:

test(std::vector<int>&&)