传递具有 std::move 函数签名的向量

Passing vector with std::move function signature

考虑下面的代码

void foo(std::vector<int> v)
{
   //do something here
}
//calling the function
vector<int> v1 = {1,2,3};
foo(std::move(v1));

我的问题是,函数 foo 不是应该具有签名 void foo(std::vector<int>&& v) 才能获取向量的 r 值引用吗?

My question is, isnt the function foo supposed to have signature void foo(std::vector<int>&& v) for it to be able to take the r value reference of the vector?

如果这就是您想要的,那么是的,但这并不意味着您拥有的是不正确的。当您将某些内容传递给函数时,复制会从源中初始化参数。这意味着如果你这样做

vector<int> v1 = {1,2,3};
foo(v1);

然后 foo 获得 v1 的副本。有

vector<int> v1 = {1,2,3};
foo(std::move(v1));

我们从 std::move(v1) 复制初始化 v 并且由于 std::move(v1) 是右值引用,因此为 v 选择移动构造函数并且 v1 被移动进入函数。

因此,通过按值获取,您可以让调用者选择为它提供一个临时对象,为它提供一个右值引用,这将把对象移动到函数中,或者只是让一个副本发生。如果你有 void foo(std::vector<int>&& v) 那么你只能传递一个临时的或 std::move() 一个左值。如果调用者不自己制作一个副本,然后将该副本移动到函数中,就无法允许调用者制作副本。

isn't the function foo supposed to have signature void foo(std::vector<int>&& v) for it to be able to take the r value reference of the vector?

它是std::vector<int>的移动构造函数,具有这样的签名。

函数foo()std::vector<int>对象作为参数:

void foo(std::vector<int> v) {
   // ...
}

必须以某种方式构造参数对象v。传递给foo()参数用于构造此参数对象。

通过在表达式foo(std::move(v1))中调用foo()foo()v中的参数对象被move构造.这与在表达式 foo(v1) 中调用 foo() 形成对比,后者导致参数对象 v 复制构造

因此参数对象的移动构造函数(即v,一个std::vector<int>对象)采用std::vector<int>&&

void foo(std::vector<int> v)

表示函数接受一个std::vector<int>对象作为参数。 如何构造这个参数对象取决于调用者,但随后它由foo.

拥有和使用

在来电者中,您有:

foo(/**compiler constructs the v parameter from whatever is here**/);

因此:

vector<int> v1 = {1,2,3};
foo(v1); // This constructs the parameter `v` as a copy of `v1`.

相比
vector<int> v1 = {1,2,3};
foo(std::move(v1)); // This constructs the parameter `v` by moving from the value of `v1`.

两者都有效,但它们做的事情略有不同。


void foo(std::vector<int>&& v)

表示函数接受一个reference作为参数,它引用了别处的std::vector<int>,也意味着调用者不应该使用该参数在此函数完成后,因为调用者打算以某种方式使其无效。

语言有助于防止此处出现错误

  • 强制您传递一个临时值(这样调用者就不会在 foo 完成后不小心尝试使用引用的 vector 的值),
  • 或者强迫你调用std::move,向编译器保证你不会在foo完成后尝试使用引用的vector的值)