182

私はここでこれを見ました: 基本クラスのMove Constructorを呼び出すMove Constructor

誰かが説明できますか:

  1. と の違いstd::movestd::forwardできればいくつかのコード例で?
  2. 簡単に考える方法と、どちらをいつ使用するか
4

4 に答える 4

169

std::moveオブジェクトを受け取り、それを一時(右辺値)として扱うことができます。これはセマンティック要件ではありませんが、通常、右辺値への参照を受け入れる関数はそれを無効にします。がstd::move表示されている場合は、オブジェクトの値を後で使用してはならないことを示していますが、新しい値を割り当てて使用を続けることができます。

std::forward単一のユースケースがあります。テンプレート化された関数パラメーター(関数内)を、呼び出し元がそれを渡すために使用した値カテゴリー(左辺値または右辺値)にキャストします。これにより、右辺値引数を右辺値として渡し、左辺値を左辺値として渡すことができます。これは「完全転送」と呼ばれるスキームです。

説明するために:

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

ハワードが述べているように、これらの関数は両方とも単に参照型にキャストされるため、類似点もあります。ただし、これらの特定のユースケース(右辺値参照キャストの有用性の99.9%をカバー)以外では、static_cast直接使用して、実行していることの適切な説明を記述する必要があります。

于 2012-03-15T09:08:36.523 に答える
63

std::forwardとはどちらもstd::moveキャストにすぎません。

X x;
std::move(x);

上記は、タイプ X の左辺値式xをタイプ X の右辺値式 (正確には xvalue) にキャストします。 move右辺値を受け入れることもできます:

std::move(make_X());

この場合、これは恒等関数です: タイプ X の右辺値を取り、タイプ X の右辺値を返します。

を使用std::forwardすると、宛先をある程度選択できます。

X x;
std::forward<Y>(x);

X 型の左辺値式xを Y 型の式にキャストします。Y の値には制約があります。

Y は、X のアクセス可能な Base、または X の Base への参照にすることができます。Y は、X、または X への参照にすることができforwardます。Y は、アクセス可能な Base 変換を介する場合を除き、X から単に変換可能な型にすることはできません。

Y が左辺値参照の場合、結果は左辺値式になります。Y が左辺値参照でない場合、結果は右辺値 (正確には xvalue) 式になります。

forwardY が左辺値参照でない場合にのみ、右辺値引数を取ることができます。つまり、右辺値を左辺値にキャストすることはできません。これは安全上の理由によるもので、一般的にダングリング参照につながるためです。ただし、右辺値を右辺値にキャストすることは問題なく許可されています。

許可されていないものに Y を指定しようとすると、エラーは実行時ではなくコンパイル時にキャッチされます。

于 2012-03-12T17:52:06.427 に答える
21

std::forward関数に渡されたのとまったく同じ方法でパラメーターを転送するために使用されます。ここに示すように:

std::forward を使用して引数を転送するのはいつですか?

std::moveオファー オブジェクトを右辺値として使用すると、ムーブ コンストラクターまたは右辺値を受け入れる関数と一致する可能性があります。それ自体が右辺値でないstd::move(x)場合でも、それを行います。x

于 2012-03-12T17:27:59.157 に答える