何时使用移入函数调用

when to use move in function calls

本文关键字:函数调用 移入 何时使      更新时间:2023-10-16

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

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

当函数接受右值引用时,您必须提供右值(通过已经具有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操作),你将不再需要它在调用站点,所以你想转移所有权,而不是复制然后"立即"丢失原始。那是你移动它的时候。

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 年以来强制要求进行这种"优化",因此您可以说在这种情况下添加"冗余"std::move实际上是有害的)。

此外,如果你传递的东西非常小(特别是一个不可能有移动构造函数的非类的东西,更不用说一个有意义的东西了!),或者你知道你正在传递一个接受其参数的函数,std::moveconst-ly;在这种情况下,由你决定是否要保存一个不会做任何事情的std::move的添加源代码分散注意力,这取决于你: 从表面上看,这是明智的,但在模板中,您可能不太确定。