私はここでこれを見ました: 基本クラスのMoveコンストラクターを呼び出すMoveコンストラクター
誰かが説明できますか:
- 差
std::move
とstd::forward
、好ましくは、いくつかのコード例をしますか? - それを簡単に考える方法、およびいつ使用するか
move
を動かしforward
たいときや、完全転送を使いたいときに使います。これはここではロケット科学ではありません;)
私はここでこれを見ました: 基本クラスのMoveコンストラクターを呼び出すMoveコンストラクター
誰かが説明できますか:
std::move
とstd::forward
、好ましくは、いくつかのコード例をしますか?move
を動かしforward
たいときや、完全転送を使いたいときに使います。これはここではロケット科学ではありません;)
回答:
std::move
オブジェクトを受け取り、それを一時的なもの(右辺値)として扱うことができます。これは意味上の要件ではありませんが、通常、右辺値への参照を受け入れる関数はそれを無効にします。が表示std::move
されている場合は、オブジェクトの値を後で使用するべきではないことを示していますが、新しい値を割り当てて引き続き使用できます。
std::forward
単一のユースケースがあります。テンプレート化された関数パラメーター(関数内)を、呼び出し元がそれを渡すために使用した値カテゴリー(lvalueまたはrvalue)にキャストします。これにより、右辺値引数を右辺値として渡すことができ、左辺値を左辺値として渡すことができます。これは、「完全転送」と呼ばれる方式です。
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::forward
とstd::move
何もなく、キャストされません。
X x;
std::move(x);
上記は、x
タイプXの左辺値式をタイプXの右辺値式(正確にはx値)にキャストします。 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への参照です。Cv修飾子をforward
でキャストできませんが、cv修飾子を追加できます。Yは、アクセス可能なBase変換を除いて、Xから単に変換できる型であってはなりません。
Yが左辺値参照の場合、結果は左辺値式になります。Yが左辺値参照でない場合、結果は右辺値(正確にはx値)式になります。
forward
Yが左辺値参照でない場合にのみ、右辺値引数を取ることができます。つまり、右辺値を左辺値にキャストすることはできません。これは安全上の理由からです。これを行うと、参照がぶら下がってしまうためです。しかし、右辺値を右辺値にキャストすることは問題なく、許可されます。
Yを許可されていないものに指定しようとすると、エラーは実行時ではなくコンパイル時にキャッチされます。
std::forward
を使用してオブジェクトを関数に完全に転送した場合、その関数が実行された後、そのオブジェクトを使用できますか?の場合std::move
、これは未定義の動作であることを認識しています。
move
:stackoverflow.com/a/7028318/576911の 場合forward
、左辺値を渡すと、APIは左辺値を受け取ったかのように反応します。通常、これは値が変更されないことを意味します。しかし、それが非定数の左辺値である場合、APIがそれを変更した可能性があります。右辺値を渡す場合、これは通常、APIが右辺値から移動した可能性があることを意味するため、stackoverflow.com / a / 7028318/576911が適用されます。
std::forward
関数に渡されたとおりにパラメーターを転送するために使用されます。ここに示すように:
いつstd :: forwardを使用して引数を転送するのですか?
を使用std::move
すると、オブジェクトが右辺値として提供され、移動コンストラクタまたは右辺値を受け入れる関数と一致する可能性があります。それ自体が右辺値ではないstd::move(x)
場合でもx
、それを行います。