可能重复:
什么是移动语义?
我最近参加了一个 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
是从一个右值1的对象构造,但它本身是一个左值,而不是一个右值。如果它有名称(在这种情况下为),那么它是一个左值并且不会自动移动,但如果它没有名称( 的结果),那么它是一个右值,如果可以的话,它会自动移动到它的结果中。类型(在这种情况下t
t
3+4
T&&
) 几乎与变量的值类别(在本例中为左值)无关。
话虽这么说,如果您在代码中T&& t
编写了代码,则意味着您引用了一个临时变量,如果您愿意,可以销毁。如果您需要多次访问该变量,您不希望std::move
从中访问,否则它将失去它的价值。但是,如果您愿意,最后一次访问它对另一个t
人来说是安全的。(而且 95% 的时间,这就是你想要做的)。所有这些也适用于 变量。std::move
T
auto&&
1.如果T
是模板类型,T&&
则改为转发引用,在这种情况下你使用std::forward<T>(t)
而不是std::move(t)
最后一次。看到这个问题。
我发现这篇文章对一般的右值引用主题很有启发性。他在最后提到std::move
。这可能是最相关的报价:
我们需要使用
std::move
, from<utility>
--std::move
是一种说法,“好吧,老实说我知道我有一个左值,但我希望它是一个右值。”std::move
本身不移动任何东西;它只是将左值转换为右值,以便您可以调用移动构造函数。
假设您有一个如下所示的移动构造函数:
MyClass::MyClass(MyClass&& other): myMember(other.myMember)
{
// Whatever else.
}
当您使用语句other.myMember
时,返回的值是一个左值。因此代码使用复制构造函数来初始化this->myMember
. 但由于这是一个移动构造函数,我们知道它other
是一个临时对象,因此它的成员也是如此。所以我们真的很想使用更高效的移动构造函数来初始化this->myMember
. Usingstd::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 获取临时对象的内容而不进行复制。
阅读更多关于右值引用和从维基百科移动构造函数的信息。