ホームページ >バックエンド開発 >C++ >右辺値参照が右辺値にのみバインドされることになっている場合、 std::move() はどのように左辺値にバインドするのでしょうか?

右辺値参照が右辺値にのみバインドされることになっている場合、 std::move() はどのように左辺値にバインドするのでしょうか?

DDD
DDDオリジナル
2024-11-14 10:46:011035ブラウズ

How does std::move() bind to lvalues when rvalue references are supposed to only bind to rvalues?

std::move の変換マジックの謎を解明する

std::move() を呼び出すと、参照されるrvalue パラメーターは lvalue にバインドできますが、通常は rvalue 参照への付加が制限されます。 std::move() の実装を詳しく調べると、この明らかな矛盾の鍵が明らかになります。

std::move() 実装の分析

洗練されたものから始めるのバージョンstd::move():

template <typename T>
typename remove_reference<T>::type&& move(T&& arg) {
  return static_cast<typename remove_reference<T>::type&&>(arg);
}

ケース 1: 右辺値を使用した move() の呼び出し

move() が一時関数などの右辺値とともに使用される場合object:

Object a = std::move(Object()); // Object() is temporary, hence prvalue

結果として得られるテンプレートのインスタンス化

remove_reference<Object>::type&& move(Object&& arg) {
  return static_cast<remove_reference<Object>::type&&>(arg);
}

remove_reference は T& を T に、または T&& を T に変換し、Object はプレーンな値であるため、最終的な関数の形態は次のようになります。

Object&& move(Object&& arg) {
  return static_cast<Object&&>(arg);
}

名前が付けられているため、キャストは重要です右辺値参照は左辺値として扱われます。

ケース 2: move() を呼び出します。左辺値

move() が左辺値で呼び出された場合:

Object a; // a is an lvalue
Object b = std::move(a);

結果としての move() のインスタンス化は次のようになります:

remove_reference<Object&>::type&& move(Object& && arg) {
  return static_cast<remove_reference<Object&>::type&&>(arg);
}

ここでも、remove_reference は Object& を変換します。オブジェクトに、 yielding:

Object&& move(Object& && arg) {
  return static_cast<Object&&>(arg);
}

参照折りたたみの本質

オブジェクト& && とその左辺値へのバインド機能を理解することが、謎を解く鍵です。 C 11 では、参照の折りたたみに関する特別なルールが導入されており、次のように規定されています。

Object & && = Object &
Object & &&& = Object &
Object && & = Object &
Object && &&& = Object &&

したがって、Object& && は、実際には、簡単に左辺値にバインドできる典型的な左辺値参照である Object& に変換されます。

結果関数

これらのルールを適用すると、最終関数関数は次のようになります。

Object&& move(Object& arg) {
  return static_cast<Object&&>(arg);
}

右辺値のインスタンス化をミラーリングし、その引数を右辺値参照にキャストすることで、均一な動作が保証されます。

remove_reference の重要性

remove_reference の目的は、代替案を検討すると明らかになります。 function:

template <typename T>
T&& wanna_be_move(T&& arg) {
  return static_cast<T&&>(arg);
}

左辺値:

Object& && wanna_be_move(Object& && arg) {
  return static_cast<Object& &&&>(arg);
}

でインスタンス化された場合、参照折りたたみルールを適用すると、使用できない移動のような関数が明らかになり、左辺値引数に対して左辺値が返されます。原因は、remove_reference の欠如であり、右辺値参照への適切な変換が妨げられます。

以上が右辺値参照が右辺値にのみバインドされることになっている場合、 std::move() はどのように左辺値にバインドするのでしょうか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。