何时使用移动函数调用

max*_*ann 12 c++ move

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

我知道在返回局部变量时不应该使用它,因为这会破坏返回值的优化,但是我真的不明白在函数调用中将值转换为rvalue真正有帮助。

Vit*_*meo 13

当一个函数接受一个右值引用时,您必须提供一个右值(通过已有一个prvaluestd::move用于创建一个xvalue)。例如

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

std::string s;

foo(s);            // Compile-time error
foo(std::move(s)); // OK
foo(std::string{}) // OK
Run Code Online (Sandbox Code Playgroud)

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

void bar(std::string s);

std::string s;

bar(s);             // Copies into `s`
bar(std::move(s));  // Moves into `s`
Run Code Online (Sandbox Code Playgroud)

当函数接受转发引用时,您可以使用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
Run Code Online (Sandbox Code Playgroud)

  • 因此,当我不再需要该变量时,就可以使用std :: move了吗? (2认同)
  • @maxbachmann因为(a)没有什么可移动的(移动主要是隐藏在指针后面的间接资源),并且(b)没有移动它们的机制[没有移动ctor!] (2认同)

Lig*_*ica 9

当您有一些实质性的对象,并且将其作为参数传递给函数(例如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!
Run Code Online (Sandbox Code Playgroud)

与:

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...
Run Code Online (Sandbox Code Playgroud)

如果未应用RVO,则在返回局部变量时会自动发生这种情况(请注意,自C ++ 17以来就强制执行了这样的“优化”操作,因此您可以说std::move在这种情况下添加“冗余” 实际上可以有害)。

同样,std::move如果您传递的是很小的东西(特别是不能具有move构造函数的非类的东西,更不用说有意义的东西了),或者您知道您正在传递给一个接受其参数const-ly 的函数,这也是没有意义的。; 在这种情况下,您是否要保存std::move不会引起任何影响的附加源代码取决于您自己:这从表面上看是明智的,但是在模板中,您可能不确定。