std :: move和std :: forward之间有什么区别
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了std :: move和std :: forward之间有什么区别相关的知识,希望对你有一定的参考价值。
我在这里看到了这个:Move Constructor calling base-class Move Constructor
有人能解释一下:
std::move
和std::forward
之间的区别,最好是一些代码示例?- 如何轻松思考,何时使用哪个
std::move
获取一个对象并允许您将其视为临时(右值)。虽然它不是语义要求,但通常接受对rvalue的引用的函数将使其无效。当您看到std::move
时,它表示之后不应使用该对象的值,但您仍可以分配新值并继续使用它。
std::forward
有一个用例:将模板化函数参数(在函数内)转换为调用者用于传递它的值类别(左值或右值)。这允许rvalue参数作为rvalues传递,并且lvalues作为lvalues传递,这是一种称为“完美转发”的方案。
void overloaded( int const &arg ) { std::cout << "by lvalue
"; }
void overloaded( int && arg ) { std::cout << "by rvalue
"; }
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:
";
forwarding( 5 );
std::cout << "initial caller passes lvalue:
";
int x = 5;
forwarding( x );
}
正如霍华德所提到的那样,这些函数只是简单地转换为引用类型,也有相似之处。但是在这些特定用例之外(其覆盖了rvalue参考演员的99.9%的有用性),你应该直接使用static_cast
并写下你正在做的事情的一个很好的解释。
std::forward
和std::move
都不过是演员。
X x;
std::move(x);
上面将类型X的左值表达式x
转换为类型X的rvalue表达式(准确地说是xvalue)。 move
也可以接受右值:
std::move(make_X());
在这种情况下,它是一个标识函数:取一个类型为X的右值并返回一个类型为X的右值。
使用std::forward
,您可以在某种程度上选择目的地:
X x;
std::forward<Y>(x);
将类型X的左值表达式x
转换为类型Y的表达式。对Y的约束有约束。
Y可以是X的可访问基数,也可以是对X的基数的引用.Y可以是X,也可以是对X的引用。不能使用forward
抛弃cv限定符,但可以添加cv限定符。除了通过可访问的Base转换之外,Y不能是仅可从X转换的类型。
如果Y是左值引用,则结果将是左值表达式。如果Y不是左值引用,则结果将是rvalue(精确的xvalue)表达式。
仅当Y不是左值参考时,forward
才能获取rvalue参数。也就是说,你不能将左值转换为左值。这是出于安全原因,因为这样做通常会导致悬挂参考。但是将rvalue转换为右值是可以的并且允许。
如果您尝试将Y指定为不允许的内容,则错误将在编译时捕获,而不是在运行时捕获。
std::forward
用于完全按照传递给函数的方式转发参数。就像这里显示的那样:
When to use std::forward to forward arguments?
使用std::move
提供一个对象作为右值,可能匹配移动构造函数或接受rvalues的函数。即使std::move(x)
本身不是rvalue,它也会为x
做到这一点。
以上是关于std :: move和std :: forward之间有什么区别的主要内容,如果未能解决你的问题,请参考以下文章
std :: move和std :: forward之间有什么区别