为什么在C++ 11中使用&&时使用std :: move?

pyC*_*hon 59 c++ move-semantics c++11

可能重复:
有人可以向我解释移动语义吗?

我最近参加了一个C++ 11研讨会,并给出了以下一些建议.

when you have && and you are unsure, you will almost always use std::move
Run Code Online (Sandbox Code Playgroud)

任何人都可以向我解释为什么你应该使用std::move而不是某些替代品以及某些不应该使用的情况std::move

Moo*_*uck 85

首先,在我将要解决的问题中可能存在一种误解:
每当你T&& t在代码中看到(并且T是实际类型,而不是模板类型)时,请记住值类别t是左值(引用),而不是右值(暂时的)了.这很令人困惑.的T&&仅仅是指t构造从一个对象,它是一个rvalue 1,但t 本身是一个左值,而不是一个右值.如果它有一个名字(在这种情况下t),那么它是一个左值并且不会自动移动,但是如果它没有名字(结果3+4)那么它就是一个右值并且如果可以的话会自动移入它的结果.该类型(在这种情况下T&&)几乎无关变量的值类型(在这种情况下,左值).

话虽这么说,如果你T&& t写在你的代码,这意味着你有一个变量的引用一个暂时的,它是确定摧毁,如果你想.如果您需要多次访问该变量,您希望std::move从中获取该变量,否则它将失去它的值.但是如果你愿意的话,你最后一次t接受std::move它对另一个人来说是安全的T.(95%的时间,这就是你想要做的).所有这些也适用于 auto&&变量.

1. if T是模板类型,T&&而不是转发引用,在这种情况下,您使用std::forward<T>(t)而不是std::move(t)最后一次.看到这个问题.

  • @pyCthon:对于通用引用,你想最后一次使用`std :: forward <T>(t)`而不是`std :: move(t)`. (7认同)
  • 有一点要记住,如果你看到一个名为**的变量,那么它是否被声明为`&&`("rvalue")`&`(reference)或``(copy)无关紧要 - 它总是被视为**左值**.您可以将真正的右值引用视为临时内容,只能从函数返回(您自己的,或包含在std :: move()中 - 简而言之 - 返回参数). (5认同)
  • @ G.Samaras:rvalues是表达式(函数和数学运算)的未命名结果.例如,`myintx + myinty`的结果本身就是一个`int`,但是没有名字,所以它将是一个rvalue.你可以将它传递给一个期望rvalue(`&&`)的函数,但是你不能将它传递给一个函数,它指的是一个左值引用(`&`).同样,你不能将`myintx`传递给期望rvalue(`&&`)的函数,因为它有一个名字.要"取消命名"一个对象,告诉编译器移动该对象是安全的,使用`std :: move`函数. (3认同)

Xav*_*olt 27

我发现这篇文章对rvalue引用的主题非常有启发性.他提到std::move了最后.这可能是最相关的引用:

我们需要使用std::move,从<utility>- std::move是一种说法,"好吧,对上帝诚实,我知道我有一个左值,但我希望它是一个左值." std::move它本身不会移动任何东西; 它只是将左值变为右值,以便您可以调用移动构造函数.


假设您有一个如下所示的移动构造函数:

MyClass::MyClass(MyClass&& other): myMember(other.myMember)
{
    // Whatever else.
}
Run Code Online (Sandbox Code Playgroud)

使用该语句时other.myMember,返回的值是左值.因此代码使用复制构造函数进行初始化this->myMember.但由于这是一个移动构造函数,我们知道这other是一个临时对象,因此它的成员也是如此.所以我们真的想用更高效的移动构造函数来初始化this->myMember.使用std::move确保编译器other.myMember像rvalue引用一样处理并调用move构造函数,因为您希望它:

MyClass::MyClass(MyClass&& other): myMember(std::move(other.myMember))
{
    // Whatever else.
}
Run Code Online (Sandbox Code Playgroud)

只是不要使用std::move你需要保留的对象 - 移动构造函数几乎可以保证将传递给它们的任何对象弄脏.这就是为什么他们只与临时使用.

希望有所帮助!