Percer le mystère de la magie de conversion de std::move
Lors de l'invocation de std::move(), il est déroutant d'observer que le Le paramètre rvalue peut être lié aux lvalues, qui ne peuvent généralement pas être attachées aux références rvalue. Plonger dans l'implémentation de std::move() révèle la clé de cet apparent paradoxe.
Disséquer l'implémentation de std::move()
Commencer par l'implémentation raffinée version de std::move():
template <typename T> typename remove_reference<T>::type&& move(T&& arg) { return static_cast<typename remove_reference<T>::type&&>(arg); }
Cas 1 : Invocation de move() avec Rvalues
Lorsque move() est utilisé avec des rvalues, comme un objet temporaire :
Object a = std::move(Object()); // Object() is temporary, hence prvalue
L'instanciation du modèle résultant est :
remove_reference<Object>::type&& move(Object&& arg) { return static_cast<remove_reference<Object>::type&&>(arg); }
Depuis remove_reference transforme T& en T ou T&& en T, et Object est une valeur simple, la morphologie finale de la fonction devient :
Object&& move(Object&& arg) { return static_cast<Object&&>(arg); }
Le cast est crucial puisque les références rvalue nommées sont traitées comme des lvalues.
Cas 2 : Invocation de move() avec Lvalues
Lorsque move() est invoqué avec des lvalues :
Object a; // a is an lvalue Object b = std::move(a);
L'instanciation move() résultante est :
remove_reference<Object&>::type&& move(Object& && arg) { return static_cast<remove_reference<Object&>::type&&>(arg); }
Encore une fois, remove_reference traduit Object& en Object, ce qui donne :
Object&& move(Object& && arg) { return static_cast<Object&&>(arg); }
L'essence de l'effondrement des références
Comprendre l'objet& && et sa capacité à se lier aux valeurs l est la clé pour résoudre l’énigme. C 11 introduit des règles spéciales pour la réduction des références, qui dictent :
Object & && = Object & Object & &&& = Object & Object && & = Object & Object && &&& = Object &&
Ainsi, Object& && se traduit en fait par Object&, une référence lvalue typique qui se lie sans effort aux lvalues.
Le Fonction résultante
Avec ces règles en jeu, la fonction finale devient :
Object&& move(Object& arg) { return static_cast<Object&&>(arg); }
En reflétant l'instanciation des rvalues, il convertit son argument en une référence rvalue, garantissant ainsi un comportement uniforme.
L'importance de remove_reference
Le but de remove_reference devient évident lors de l'examen d'une fonction alternative :
template <typename T> T&& wanna_be_move(T&& arg) { return static_cast<T&&>(arg); }
Quand instancié avec une lvalue :
Object& && wanna_be_move(Object& && arg) { return static_cast<Object& &&&>(arg); }
l'application de règles de réduction de référence révèle une fonction de type déplacement inutilisable, renvoyant des lvalues pour les arguments lvalue. Le coupable est l'absence de remove_reference, qui entrave la conversion correcte en références rvalue.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!