C++ std::move 和 std::forward 有什么区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9671749/
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
What's the difference between std::move and std::forward
提问by aCuria
I saw this here: Move Constructor calling base-class Move Constructor
我在这里看到了: 移动构造函数调用基类移动构造函数
Could someone explain:
有人可以解释一下:
- the difference between
std::move
andstd::forward
, preferably with some code examples? - How to think about it easily, and when to use which
- 之间的差
std::move
和std::forward
,优选用一些代码示例? - 如何轻松思考,以及何时使用哪个
采纳答案by Potatoswatter
std::move
takes an object and allows you to treat it as a temporary (an rvalue). Although it isn't a semantic requirement, typically a function accepting a reference to an rvalue will invalidate it. When you see std::move
, it indicates that the value of the object should not be used afterwards, but you can still assign a new value and continue using it.
std::move
接受一个对象并允许您将其视为临时对象(右值)。尽管这不是语义要求,但通常接受对右值的引用的函数会使它无效。当您看到 时std::move
,表示该对象的值以后不应使用,但您仍然可以分配一个新值并继续使用它。
std::forward
has a single use case: to cast a templated function parameter (inside the function) to the value category (lvalue or rvalue) the caller used to pass it. This allows rvalue arguments to be passed on as rvalues, and lvalues to be passed on as lvalues, a scheme called "perfect forwarding."
std::forward
有一个用例:将模板化函数参数(在函数内部)转换为调用者用来传递它的值类别(左值或右值)。这允许将右值参数作为右值传递,将左值作为左值传递,这种方案称为“完美转发”。
To illustrate:
为了举例说明:
void overloaded( int const &arg ) { std::cout << "by lvalue\n"; }
void overloaded( int && arg ) { std::cout << "by rvalue\n"; }
template< typename t >
/* "t &&" with "t" being template param is special, and adjusts "t" to be
(for example) "int &" or non-ref "int" so std::forward knows what to do. */
void forwarding( t && arg ) {
std::cout << "via std::forward: ";
overloaded( std::forward< t >( arg ) );
std::cout << "via std::move: ";
overloaded( std::move( arg ) ); // conceptually this would invalidate arg
std::cout << "by simple passing: ";
overloaded( arg );
}
int main() {
std::cout << "initial caller passes rvalue:\n";
forwarding( 5 );
std::cout << "initial caller passes lvalue:\n";
int x = 5;
forwarding( x );
}
As Howard mentions, there are also similarities as both these functions simply cast to reference type. But outside these specific use cases (which cover 99.9% of the usefulness of rvalue reference casts), you should use static_cast
directly and write a good explanation of what you're doing.
正如 Howard 所提到的,这两个函数也有相似之处,因为它们都简单地转换为引用类型。但是在这些特定用例之外(涵盖了 99.9% 的右值引用转换的有用性),您应该static_cast
直接使用并为您正在做什么写一个很好的解释。
回答by Howard Hinnant
Both std::forward
and std::move
are nothing but casts.
无论std::forward
和std::move
什么都不是,但转换。
X x;
std::move(x);
The above casts the lvalue expression x
of type X to an rvalue expression of type X (an xvalue to be exact). move
can also accept an rvalue:
以上将x
X 类型的左值表达式转换为X 类型的右值表达式(确切地说是 xvalue)。 move
也可以接受右值:
std::move(make_X());
and in this case it is an identity function: takes an rvalue of type X and returns an rvalue of type X.
在这种情况下,它是一个恒等函数:采用 X 类型的右值并返回 X 类型的右值。
With std::forward
you can select the destination to some extent:
随着std::forward
您可以选择目标在一定程度上:
X x;
std::forward<Y>(x);
Casts the lvalue expression x
of type X to an expression of type Y. There are constraints on what Y can be.
将x
X 类型的左值表达式转换为 Y 类型的表达式。对 Y 可以是什么有限制。
Y can be an accessible Base of X, or a reference to a Base of X. Y can be X, or a reference to X. One can not cast away cv-qualifiers with forward
, but one can add cv-qualifiers. Y can not be a type that is merely convertible from X, except via an accessible Base conversion.
Y 可以是 X 的可访问基数,或对 X 基数的引用。Y 可以是 X,或对 X 的引用。不能用 丢弃 cv 限定符forward
,但可以添加 cv 限定符。Y 不能是只能从 X 转换的类型,除非通过可访问的 Base 转换。
If Y is an lvalue reference, the result will be an lvalue expression. If Y is not an lvalue reference, the result will be an rvalue (xvalue to be precise) expression.
如果 Y 是左值引用,则结果将是左值表达式。如果 Y 不是左值引用,则结果将是右值(准确地说是 xvalue)表达式。
forward
can take an rvalue argument only if Y is not an lvalue reference. That is, you can not cast an rvalue to lvalue. This is for safety reasons as doing so commonly leads to dangling references. But casting an rvalue to rvalue is ok and allowed.
forward
仅当 Y 不是左值引用时才可以采用右值参数。也就是说,您不能将右值转换为左值。这是出于安全原因,因为这样做通常会导致悬空引用。但是将右值转换为右值是可以的并且是允许的。
If you attempt to specify Y to something that is not allowed, the error will be caught at compile time, not run time.
如果您尝试将 Y 指定为不允许的内容,则会在编译时而非运行时捕获错误。
回答by Bo Persson
std::forward
is used to forwarda parameter exactly the way it was passed to a function. Just like shown here:
std::forward
用于完全按照传递给函数的方式转发参数。就像这里显示的那样:
When to use std::forward to forward arguments?
Using std::move
offers an object as an rvalue, to possibly match a move constructor or a function accepting rvalues. It does that for std::move(x)
even if x
is not an rvalue by itself.
使用std::move
提供对象作为右值,以可能匹配移动构造函数或接受右值的函数。std::move(x)
即使它x
本身不是右值,它也会这样做。