关于c ++:为什么使用std::move当你有&&

Why do you use std::move when you have && in C++11?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
Can someone please explain move semantics to me?

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

1
when you have && and you are unsure, you will almost always use std::move

有人能向我解释为什么你应该使用std::move,而不是一些替代品,有些情况下你不应该使用std::move


首先,我要解决的问题可能有一个误解:每当您在代码中看到T&& t(t是实际类型,而不是模板类型)时,请记住,t的值类别是左值(引用),不再是右值(临时)。这很混乱。T&&仅仅意味着t是由一个右值为1的对象构造的,但是t本身是一个左值,而不是一个右值。如果它有一个名称(在本例中是t),那么它是一个左值,不会自动移动,但是如果它没有名称(3+4的结果),那么它是一个右值,如果可以,它会自动移动到结果中。类型(在本例中为T&&)几乎与变量的值类别(在本例中为lvalue)无关。

也就是说,如果您的代码中写入了T&& t,这意味着您有一个对临时变量的引用,如果您想销毁它是可以的。如果需要多次访问该变量,则不希望从该变量中删除cx1(1),否则它将失去其值。但你上次访问t时,如果你愿意,对std::move是安全的,对另一个t是有价值的。(95%的时候,这就是你想要做的)。所有这些也适用于auto&&变量。

1。如果t是模板类型,那么T&&是转发引用,在这种情况下,最后一次使用std::forward(t)而不是std::move(t)。看看这个问题。


我发现这篇文章对于一般的右值引用的主题很有启发性。他最后提到了以东。这可能是最相关的报价:

We need to use std::move, from -- std::move is a way of
saying,"ok, honest to God I know I have an lvalue, but I want it to
be an rvalue." std::move does not, in and of itself, move anything; it
just turns an lvalue into an rvalue, so that you can invoke the move
constructor.

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

1
2
3
4
MyClass::MyClass(MyClass&& other): myMember(other.myMember)
{
    // Whatever else.
}

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

1
2
3
4
MyClass::MyClass(MyClass&& other): myMember(std::move(other.myMember))
{
    // Whatever else.
}

只是不要在需要保留的对象上使用std::move,move构造函数几乎可以保证将传递给它们的任何对象弄脏。这就是为什么他们只和临时工一起使用。

希望有帮助!


当您有一个类型为T&&的右值对象时,这意味着可以安全地移动该对象,因为以后没有其他对象依赖于其内部状态。

因为移动永远不会比复制更昂贵,所以您几乎总是希望移动它。要移动它,必须使用std::move函数。

你什么时候应该避开std::move,即使它是安全的?我不会在一些小例子中使用它,例如:

1
2
 int x = 0;
 int y = std::move(x);

除此之外,我没有看到任何负面影响。如果不使代码复杂化,那么应该尽可能地移动imho。

另一个不想移动的例子是返回值。该语言保证返回值(至少)被移动,因此不应写入

1
return std::move(x); // not recommended

(如果幸运的话,返回值优化点击,这比移动操作更好。)


当需要将对象的内容"传输"到其他地方时,可以使用"移动",而不需要进行复制。使用std::move,对象还可以在不进行复制的情况下获取临时对象的内容。

签出此链接