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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14486367/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 18:22:30  来源:igfitidea点击:

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

c++c++11move-semantics

提问by pyCthon

Possible Duplicate:
What is move semantics?

可能的重复:
什么是移动语义?

I recently attended a C++11 seminar and the following tidbit of advice was given.

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

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

Could any one explain to me why you should use std::moveas opposed to some alternatives and some cases when you should not use std::move?

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

回答by Mooing Duck

First, there's probably a misconception in the question I'll address:
Whenever you see T&& tin code (And T is an actual type, not a template type), keep in mind the value category of tis an lvalue(reference), not an rvalue(temporary) anymore. It's very confusing. The T&&merely means that tis constructedfrom an object that was an rvalue 1, but titselfis an lvalue, not an rvalue. If it has a name (in this case, t) then it's an lvalue and won't automatically move, but if it has no name (the result of 3+4) then it is an rvalue and will automaticallymove into it's result if it can. The type(in this case T&&) has almost nothing to do with the value category of the variable (in this case, an lvalue).

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

That being said, if you have T&& twritten in your code, that means you have a reference to a variable that wasa temporary, and it is ok to destroy if you want to. If you need to access the variable multiple times, you do notwant to std::movefrom it, or else it would lose it's value. But the last time you acccess tit is safe to std::moveit's value to another Tif you wish. (And 95% of the time, that's what you want to do). All of this also applies to auto&&variables.

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

1. if Tis a template type, T&&is a forwarding reference instead, in which case you use std::forward<T>(t)instead of std::move(t)the last time. See this question.

1.ifT是模板类型,T&&是转发引用代替,在这种情况下你用的std::forward<T>(t)不是std::move(t)最后一次。看到这个问题

回答by Xavier Holt

I found this articleto be pretty enlightening on the subject of rvalue references in general. He mentions std::movetowards the end. This is probably the most relevant quote:

我发现这篇文章对一般的右值引用主题非常有启发性。他std::move在最后提到。这可能是最相关的引用:

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

我们需要使用std::move, from <utility>--std::move是一种说法,“好吧,老实说,我知道我有一个左值,但我希望它是一个右值。” std::move本身不会移动任何东西;它只是将左值转换为右值,以便您可以调用移动构造函数。



Say you have a move constructor that looks like this:

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

MyClass::MyClass(MyClass&& other): myMember(other.myMember)
{
    // Whatever else.
}

When you use the statement other.myMember, the value that's returned is an lvalue. Thus the code uses the copyconstructor to initialize this->myMember. But since this is a move constructor, we know that otheris a temporary object, and therefore so are its members. So we really want to use the more-efficient moveconstructor to initialize this->myMember. Using std::movemakes sure that the compiler treats other.myMemberlike an rvalue reference and calls the move constructor, as you'd want it to:

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

MyClass::MyClass(MyClass&& other): myMember(std::move(other.myMember))
{
    // Whatever else.
}

Just don't use std::moveon objects you need to keep around - move constructors are pretty much guaranteed to muck up any objects passed into them. That's why they're only used with temporaries.

只是不要std::move在您需要保留的对象上使用- 移动构造函数几乎可以保证处理传递给它们的任何对象。这就是为什么它们只与临时对象一起使用。

Hope that helps!

希望有帮助!

回答by Philipp Cla?en

When you have an object of type T&&, a rvalue, it means that this object is safe to be moved, as no one else will depend on its internal state later.

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

As moving should never be more expensive than copying, you will almost always want to move it. And to move it, you have to use the std::movefunction.

由于搬家永远不会比复制更昂贵,因此您几乎总是想搬家。要移动它,您必须使用该std::move功能。

When should you avoid std::move, even if it would be safe? I wouldn't use it in trivial examples, e.g.,:

什么时候应该避免std::move,即使它是安全的?我不会在琐碎的例子中使用它,例如:

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

Beside that, I see no downsides. If it does not complicate the code, moving should be done whenever possible IMHO.

除此之外,我看不出有什么缺点。如果它不会使代码复杂化,恕我直言,应尽可能进行移动。

Another example, where you don't want to move are return values. The language guarantees that return values are (at least) moved, so you should not write

另一个示例,您不想移动的地方是返回值。该语言保证返回值(至少)被移动,所以你不应该写

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

(If you are lucky, return value optimizationhits, which is even better than a move operation.)

(如果幸运的话,返回值优化命中,这甚至比移动操作更好。)

回答by Rahul Tripathi

You can use move when you need to "transfer" the content of an object somewhere else, without doing a copy. It's also possible for an object to take the content of a temporary object without doing a copy, with std::move.

当您需要将对象的内容“转移”到其他地方而不进行复制时,您可以使用 move。对象也可以使用 std::move 获取临时对象的内容而不进行复制。

Checkout this link

结帐此链接