1. ホーム
  2. c++

[解決済み] std::moveとstd::forwardの違いは何ですか?

2022-04-20 07:09:06

質問

こちらで拝見しました。 ベースクラスの Move コンストラクタを呼び出す Move コンストラクタ

どなたか説明してください。

  1. かわり std::move std::forward できればコード例も一緒に教えてください。
  2. 簡単に考える方法と、どのタイミングでどれを使うか

解決するには?

std::move はオブジェクトを受け取り、それを一時的なもの(rvalue)として扱えるようにします。意味上の必要条件ではありませんが、通常、rvalueへの参照を受け入れる関数はそれを無効にします。あなたが std::move しかし、新しい値を代入して使い続けることは可能です。

std::forward それは、テンプレート化された関数パラメータ(関数内部)を、呼び出し元が渡すために使用した値のカテゴリ(lvalueまたはrvalue)にキャストすることです。これにより、rvalueの引数はrvalueとして渡され、lvalueはlvalueとして渡されるようになり、完璧な転送と呼ばれるスキームが実現します。

への 例える :

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

Howardが言うように、これらの関数は単に参照型にキャストするだけなので、類似点もあります。しかし、これらの特定の使用例(rvalueの参照キャストの有用性の99.9%をカバーする)以外では、以下のように使用すべきです。 static_cast を直接書いて、何をやっているのかきちんと説明しましょう。