À en juger par les commentaires
habr.com/en/post/460831/#comment_20416435 dans le prochain post et la discussion qui s'y est déroulée, l'article sur la façon de transmettre correctement les arguments au constructeur ou au setter n'entravera pas Habré. StackOverflow a beaucoup de matériel similaire, mais je ne me souviens pas de quelque chose ici.
Parce que l'exemple de cet article est tout à fait correct et que l'auteur de l'article a parfaitement raison. Voici un exemple:
Un tel code vous permet de couvrir toutes (enfin, presque toutes) les options possibles pour utiliser la classe:
std::string first{"abc"}, last{"def"}; person p1{first, last};
Comparer avec l'ancienne méthode, lorsqu'elle est passée via const &: c'est certainement pire, car elle exclut l'option (3):
Une alternative avec && est également pire, mais en sens inverse:
Si vous n'avez pas peur d'une explosion combinatoire, vous pouvez donner une chance à && (mais pourquoi? Il n'y aura pas de réel gain de vitesse, l'optimiseur ne s'assoupit pas):
Ou la même chose, seulement avec des modèles (mais encore une fois, pourquoi?):
Même si vous n'avez pas std :: string, mais un objet de votre propre grande classe écrite, et que vous voulez que les gens le fassent bouger (et non copier), alors dans ce cas, il vaut mieux interdire au constructeur de copier à partir de cette grande classe que de le passer partout par &&. C'est plus fiable et le code est plus court.
Enfin, quelques options sur la façon de NE PAS VAUT:
Et ne le faites pas non plus:
Pourquoi cela se produit-il, quel est le principe fondamental? C'est simple: un objet, en règle générale, devrait posséder ses propriétés.
Si l'objet ne veut pas posséder quelque chose, il peut alors posséder shared_ptr pour ce «quelque chose». Soit dit en passant, dans ce cas, shared_ptr doit également être transmis par valeur, et non par lien constant - il n'y a pas de différence avec le tout premier exemple au début de l'article:
Veuillez noter: std :: move pour shared_ptr est complètement légal, il élimine la surcharge de verrouillage du compteur de liens shared_ptr en mémoire (centaines de cycles CPU) et son incrément. Il n'affecte pas la durée de vie de l'objet et d'autres liens vers celui-ci. Mais (X) ne peut être fait, bien sûr, que si le lien psh dans le code ci-dessous n'est plus nécessaire.
Moralité: n'utilisez pas const & en général. Regardez selon les circonstances.
PS
Utilisez {} au lieu de () lors du passage des paramètres du constructeur. À la mode, moderne, jeune.
PPS
En conclusion, une dernière chose: std :: move () ne déplace en fait rien et se traduit en soi par zéro instructions d'assembleur. Tout ce que std :: move () fait est de mettre une "étiquette collante" spéciale sur le lien, en le transformant en une référence && - rvalue. De plus, il est possible avec cette étiquette de «faire correspondre» séparément le type de paramètre de fonction (par exemple, pour avoir une surcharge de fonction distincte pour le paramètre && - et une distincte pour le paramètre &). Le sens de l'étiquette && - est de permettre au code appelant de dire à l'appelé: «si vous voulez, vous pouvez manger la valeur de ce lien, je n'en ai plus besoin; mais seulement si vous mangez, laissez les os, alors j'ai encore besoin d'appeler le destructeur pour le squelette restant. " Avec le même succès, il serait possible de transmettre des liens & ordinaires (vous pouvez également utiliser l'objet pour les "manger"), mais avec la & sémantique, c'est mieux, car vous ne confondrez pas: où vous pouvez manger et où vous ne pouvez que sentir.
À cet égard, le nom std :: move () doit être reconnu comme extrêmement infructueux. Il serait correct de l'appeler std :: eat_me_if_you_want () ou std :: bon_appetit (). Mais std :: move () est plus court.