Maison > développement back-end > C++ > Comment std::move() se lie-t-il aux lvalues ​​alors que les références rvalue sont censées se lier uniquement aux rvalues ​​?

Comment std::move() se lie-t-il aux lvalues ​​alors que les références rvalue sont censées se lier uniquement aux rvalues ​​?

DDD
Libérer: 2024-11-14 10:46:01
original
1034 Les gens l'ont consulté

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

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);
}
Copier après la connexion

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
Copier après la connexion

L'instanciation du modèle résultant est :

remove_reference<Object>::type&& move(Object&& arg) {
  return static_cast<remove_reference<Object>::type&&>(arg);
}
Copier après la connexion

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);
}
Copier après la connexion

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);
Copier après la connexion

L'instanciation move() résultante est :

remove_reference<Object&>::type&& move(Object& && arg) {
  return static_cast<remove_reference<Object&>::type&&>(arg);
}
Copier après la connexion

Encore une fois, remove_reference traduit Object& en Object, ce qui donne :

Object&& move(Object& && arg) {
  return static_cast<Object&&>(arg);
}
Copier après la connexion

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 &&
Copier après la connexion

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);
}
Copier après la connexion

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);
}
Copier après la connexion

Quand instancié avec une lvalue :

Object& && wanna_be_move(Object& && arg) {
  return static_cast<Object& &&&>(arg);
}
Copier après la connexion

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!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal