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<<" ";
}
答案 0 :(得分:2)
我最好的猜测是编译器会自动生成
编译器将自动生成的唯一代码是针对构造函数,赋值运算符和析构函数的。那些有警告。这里发生的事情与自动生成的代码无关。当您编写test(move(v))
(对于某些类型的V
)时,可以通过两种方式使它起作用。
test
接受类型为V&&
的参数。它将很高兴地绑定到您提供的右值引用。test
接受类型为V const&
的参数。 const lvlaue引用也绑定到右值引用参数。这样,未针对移动语义进行调整的旧代码仍然可以工作。 const lvlaue参考是一个方便的后备。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>&&)