可能是重复问题:
什么是移动语义?
我最近参加了一个C++11研讨会,听到了以下的建议。
when you have && and you are unsure, you will almost always use std::move
有人能解释一下为什么要使用 std::move
而不是其他替代方案以及使用 std::move
的一些情况吗?
可能是重复问题:
什么是移动语义?
我最近参加了一个C++11研讨会,听到了以下的建议。
when you have && and you are unsure, you will almost always use std::move
有人能解释一下为什么要使用 std::move
而不是其他替代方案以及使用 std::move
的一些情况吗?
T&& t
(其中T是一个实际类型,而不是一个模板类型),请记住t
的值类别是一个左值(引用),而不再是一个右值(临时对象)。这非常令人困惑。T&&
仅仅意味着t
是从一个rvalue构造出来的1,但t
本身是一个左值,而不是一个右值。如果它有一个名称(在这种情况下,是t
),那么它就是一个左值,并且不会自动移动;但如果它没有名称(例如3+4
的结果),那么它就是一个右值,并且如果可以的话,将自动移动到它的结果中。类型(在这种情况下是T&&
)与变量的值类别(在这种情况下是一个左值)几乎没有关系。
尽管如此,如果你在代码中写了T&& t
,那么这意味着你有一个对曾经是临时对象的变量的引用,如果你愿意,可以销毁它。如果你需要多次访问该变量,则不应该从中std::move
,否则它将失去其值。但是,在最后一次访问t
时,如果你愿意,可以安全地将其值std::move
到另一个T
中(而且在95%的情况下,这就是你想要做的)。所有这些也适用于auto&&
变量。
1. 如果T
是一个模板类型,则T&&
是一个转发引用,此时你应该使用std::forward<T>(t)
而不是std::move(t)
来进行最后一次操作。请参见这个问题。
std::forward<T>(t)
而不是 std::move(t)
。 - Mooing Duck&&
(“右值”)&
(引用)还是``(拷贝)始终被认为是左值。您可以将真正的右值引用视为仅能从函数(自己的函数或通过std::move()包装的函数,简而言之-返回参数)中返回的临时对象。 - Red XIIIstd::move
。如果输入确实是rvalue,则std::forward
与std::move
相同,如果输入确实是lvalue,则不执行任何操作,因此您始终获得正确的机制。请参见此问题。 - Mooing Duckmyintx + myinty
的结果本身是一个 int
,但它没有名称,因此它将是一个 rvalue。您可以将其传递给期望 rvalue (&&
) 的函数,但不能将其传递给期望 lvalue 引用 (&
) 的函数。同样,您也无法将 myintx
传递给期望 rvalue (&&
) 的函数,因为它有一个名称。要“取消命名”对象,告诉编译器可以安全地移动该对象,请使用 std::move
函数。 - Mooing Duck我发现这篇文章对于rvalue引用的主题非常有启发性。作者在文章结尾提到了std::move
。以下是最相关的引用:
我们需要使用
std::move
,它位于<utility>
中——std::move
是一种说法,“好的,老实说我知道我有一个lvalue,但我希望它成为rvalue。”std::move
本身并没有移动任何东西;它只是将一个lvalue转换为rvalue,以便您可以调用移动构造函数。
假设你有一个长这样的移动构造函数:
MyClass::MyClass(MyClass&& other): myMember(other.myMember)
{
// Whatever else.
}
other.myMember
时,返回的值是一个左值。因此,该代码使用复制构造函数来初始化this->myMember
。但由于这是一个移动构造函数,我们知道other
是一个临时对象,因此它的成员也是临时的。因此,我们真正想要使用更高效的移动构造函数来初始化this->myMember
。使用std::move
确保编译器将other.myMember
视为右值引用并调用移动构造函数,正如您所希望的:MyClass::MyClass(MyClass&& other): myMember(std::move(other.myMember))
{
// Whatever else.
}
请不要在需要保留的对象上使用std::move
- 移动构造函数几乎肯定会破坏传入它们的任何对象。这就是为什么它们只与临时对象一起使用的原因。
希望这有所帮助!
T&&
的对象,即rvalue时,这意味着该对象可以安全地进行移动,因为没有其他人会依赖于它的内部状态。std::move
函数。std::move
呢?我不会在简单的例子中使用它,例如: int x = 0;
int y = std::move(x);
return std::move(x); // not recommended
如果你很幸运,返回值优化会发生,这比移动操作更好。
当你需要将一个对象的内容“转移”到另一个地方而不进行复制时,可以使用 move。使用 std::move 还可以使一个对象获取临时对象的内容而不进行复制。
更多信息请参考维基百科上的右值引用和移动构造函数。