何时在函数调用中使用 move

when to use move in function calls

我目前正在学习有关所有 c++11/14 功能的更多信息,想知道何时在函数调用中使用 std::move。

我知道我不应该在返回局部变量时使用它,因为这会破坏 Return 值优化,但我真的不明白在函数调用中转换为右值实际上有什么帮助。

当一个函数接受一个 右值引用 时,你必须提供一个 右值 (要么已经有一个 prvalue,或使用 std::move 创建一个 xvalue)。例如

void foo(std::string&& s);

std::string s;

foo(s);            // Compile-time error
foo(std::move(s)); // OK
foo(std::string{}) // OK

当函数接受 时,您可以使用 std::move 移动构造函数参数而不是复制构造。例如

void bar(std::string s);

std::string s;

bar(s);             // Copies into `s`
bar(std::move(s));  // Moves into `s`

当函数接受 转发引用 时,您可以使用 std::move 允许函数将对象进一步向下移动到调用堆栈中。例如

template <typename T>
void pipe(T&& x)
{
    sink(std::forward<T>(x));
}

std::string s;

pipe(s);             // `std::forward` will do nothing
pipe(std::move(s));  // `std::forward` will move
pipe(std::string{}); // `std::forward` will move

当您有一些实质性对象,并将其作为参数传递给函数(例如 API 或容器 emplace 操作)时,您将不再需要它在调用站点,因此您想要 转让所有权 ,而不是复制然后 "immediately" 丢失原始文件。那就是你移动它的时候了。

void StoreThing(std::vector<int> v);

int main()
{
    std::vector<int> v{1,2,3,4,5,6/*,.....*/};
    StoreThing(v);
}

// Copies `v` then lets it go out of scope. Pointless!

对比:

void StoreThing(std::vector<int> v);

int main()
{
    std::vector<int> v{1,2,3,4,5,6/*,.....*/};
    StoreThing(std::move(v));
}

// Better! We didn't need `v` in `main` any more...

如果未应用 RVO,则返回局部变量时会自动发生这种情况(请注意,自 C++17 以来,这样的 "optimisation" 是强制要求的,因此您说添加 "redundant" std::move 在那种情况下实际上是有害的)。

此外,如果您传递的是非常小的东西(尤其是非 class 不可能有移动构造函数的东西,更不用说有意义的东西了!),那么 std::move 也毫无意义!知道您正在传递给接受其参数 const-ly 的函数;在这种情况下,由您决定是否要保存不会执行任何操作的 std::move 添加的源代码干扰:表面上它是明智的,但在模板中您可能不太确定。