4 votes

Quel est le scénario "l'objet source est une lvalue", mentionné dans EMC++, où la sémantique de déplacement n'offre aucun gain d'efficacité ?

Au point 29 de Effective Modern C++, Scott Meyers énumère trois scénarios dans lesquels la sémantique des déplacements n'améliore pas les performances du code,

[ ] déplacer la sémantique ne vous sert à rien :

  • Aucune opération de déménagement : L'objet à déplacer ne propose pas d'opérations de déplacement [ ].
  • Ne bougez pas plus vite : [ ] des opérations de déplacement qui ne sont pas plus rapides que ses opérations de copie.
  • Déplacement non utilisable : Le contexte [ ] requiert une opération de déplacement qui n'émet pas d'exceptions, mais cette opération n'est pas déclarée. noexcept .

qui sont toutes clairement expliquées dans les pages précédentes, et en ajoute une autre

[ ] un autre scénario où la sémantique du déplacement n'offre aucun gain d'efficacité :

  • L'objet source est lvalue : À quelques exceptions près (voir par exemple le point 25), seules les valeurs r peuvent être utilisées comme source d'une opération de déplacement.

(Le point 25 est intitulé Utilisez std::move sur les références rvalue et std::forward sur les références universelles mais je ne vois pas en quoi il est lié au point qui y fait référence).

Ensuite, le texte revient essentiellement à un résumé de l'article, sans autre référence au quatrième point.

À quoi ce point fait-il référence ?

D'après ce que je comprends de la sémantique des déplacements, même si je veux passer d'une valeur lval, disons x je dois encore le convertir en une rvalue via std::move(x) (ou un équivalent static_cast ), donc techniquement je me déplace toujours à partir d'une rvalue (spécifiquement une xvalue dans ce cas), pas d'une lvalue.

Je serais donc tenté de dire qu'une lvalue ne peut pas être l'objet source d'une opération de déplacement.

Qu'est-ce que j'ai manqué à ce sujet ?

1voto

Dietmar Kühl Points 70604

Le terme lvalue fait référence à des valeurs en quelque sorte "nommées", c'est-à-dire des entités ayant plusieurs références. La sémantique du déplacement ne s'applique pas vraiment à ces valeurs, car il ne faut pas "voler" la représentation de quelque chose qui peut être référencé ailleurs. En d'autres termes, si l'objet source est une lvalue, vous ne pouvez tout simplement pas le déplacer ! Ainsi, la construction de déplacement ne fournit pas d'avantage ici. En fait, les lvalues ne se lient pas volontiers à des références rvalue - il faudrait forcer cette liaison, par exemple en utilisant la fonction std::move() .

Essentiellement, votre point de vue est tout à fait correct : une lvalue ne peut pas être la source d'une opération de déplacement - et donc les opérations de déplacement n'apportent aucun avantage lorsque des lvalues sont impliquées.

-1voto

gnasher729 Points 5011

A titre d'exemple : Vous avez une classe T avec un constructeur de mouvement. Vous avez une fonction qui retourne un objet de type T, et vous essayez de la rendre plus rapide en retournant une valeur r. Maintenant, si vous commencez avec

T x;
x.a = ...;
x.b = ...;
x.c = ...;
return x;

alors un objet x sera construit, un nouvel objet sans nom sera créé par l'instruction de retour, puis x est détruit, puis la valeur de retour est déplacée. Et finalement, l'appelant appellera le destructeur pour le résultat déplacé. Vous avez donc deux constructeurs, deux destructeurs, aucune économie.

Si vous commencez par

T x(a, b, c);
return x;

alors vous avez le même problème, deux constructeurs et destructeurs, aucune économie. Pour économiser quoi que ce soit, vous devez écrire

return T(a, b, c);

ou retourner la valeur de retour d'une autre fonction retournant un objet.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X