私はここでこれを見ました: ベースクラスの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
でcv修飾子をキャストすることはできませんが、cvを追加できます-修飾子。 Yは、アクセス可能なBase変換を除き、Xから単に変換可能な型にすることはできません。
Yが左辺値参照の場合、結果は左辺値式になります。 Yが左辺値参照でない場合、結果は右辺値(正確にはxvalue)式になります。
forward
は、Yが左辺値参照でない場合にのみ右辺値引数を取ることができます。つまり、右辺値を左辺値にキャストすることはできません。これは安全性の理由によるものです。これを行うと、一般的に参照がぶら下がります。しかし、右辺値を右辺値にキャストすることは問題ありません。
許可されていないものにYを指定しようとすると、エラーは実行時ではなくコンパイル時にキャッチされます。
_std::forward
_は、関数に渡されたとおりにパラメーターをforwardするために使用されます。ここに示すように:
引数を転送するためにstd :: forwardを使用する場合
_std::move
_を使用すると、おそらく移動コンストラクターまたは右辺値を受け入れる関数に一致するために、右辺値としてオブジェクトが提供されます。 x
自体が右辺値でない場合でも、std::move(x)
に対してそれを行います。