std :: move和std :: forward之间有什么区别

问题描述 投票:149回答:3

我在这里看到了这个:Move Constructor calling base-class Move Constructor

有人能解释一下:

  1. std::movestd::forward之间的区别,最好是一些代码示例?
  2. 如何轻松思考,何时使用哪个
c++ c++11 perfect-forwarding
3个回答
141
投票

std::move获取一个对象并允许您将其视为临时(右值)。虽然它不是语义要求,但通常接受对rvalue的引用的函数将使其无效。当您看到std::move时,它表示之后不应使用该对象的值,但您仍可以分配新值并继续使用它。

std::forward有一个用例:将模板化函数参数(在函数内)转换为调用者用于传递它的值类别(左值或右值)。这允许rvalue参数作为rvalues传递,并且lvalues作为lvalues传递,这是一种称为“完美转发”的方案。

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 );
}

正如霍华德所提到的那样,这些函数只是简单地转换为引用类型,也有相似之处。但是在这些特定用例之外(其覆盖了rvalue参考演员的99.9%的有用性),你应该直接使用static_cast并写下你正在做的事情的一个很好的解释。


55
投票

std::forwardstd::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指定为不允许的内容,则错误将在编译时捕获,而不是在运行时捕获。


20
投票

std::forward用于完全按照传递给函数的方式转发参数。就像这里显示的那样:

When to use std::forward to forward arguments?

使用std::move提供一个对象作为右值,可能匹配移动构造函数或接受rvalues的函数。即使std::move(x)本身不是rvalue,它也会为x做到这一点。

© www.soinside.com 2019 - 2024. All rights reserved.