私はここでこれを見ました: 基本クラスのMove Constructorを呼び出すMove Constructor
誰かが説明できますか:
- と の違い
std::move
、std::forward
できればいくつかのコード例で? - 簡単に考える方法と、どちらをいつ使用するか
私はここでこれを見ました: 基本クラスのMove Constructorを呼び出すMove Constructor
誰かが説明できますか:
std::move
、std::forward
できればいくつかのコード例で?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
直接使用して、実行していることの適切な説明を記述する必要があります。
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) 式になります。
forward
Y が左辺値参照でない場合にのみ、右辺値引数を取ることができます。つまり、右辺値を左辺値にキャストすることはできません。これは安全上の理由によるもので、一般的にダングリング参照につながるためです。ただし、右辺値を右辺値にキャストすることは問題なく許可されています。
許可されていないものに Y を指定しようとすると、エラーは実行時ではなくコンパイル時にキャッチされます。
std::forward
関数に渡されたのとまったく同じ方法でパラメーターを転送するために使用されます。ここに示すように:
std::forward を使用して引数を転送するのはいつですか?
std::move
オファー オブジェクトを右辺値として使用すると、ムーブ コンストラクターまたは右辺値を受け入れる関数と一致する可能性があります。それ自体が右辺値でないstd::move(x)
場合でも、それを行います。x