Il a utilisé la meilleure pratique généralement recommandée 1 à l'utilisation passer par ref const pour tous les types , à l' exception des types (builtin char
, int
, double
, etc.), pour itérateurs et des objets de fonction (lambdas, classes dérivées de std::*_function
).
Cela était particulièrement vrai avant l'existence de la sémantique des mouvements . La raison est simple: si vous passez par valeur, une copie de l'objet doit être faite et, sauf pour les très petits objets, c'est toujours plus cher que de passer une référence.
Avec C ++ 11, nous avons acquis une sémantique de mouvement . En un mot, la sémantique de mouvement permet que, dans certains cas, un objet puisse être passé «par valeur» sans le copier. C'est notamment le cas lorsque l'objet que vous passez est une valeur r .
En soi, déplacer un objet est toujours au moins aussi cher que passer par référence. Cependant, dans de nombreux cas, une fonction copiera de toute façon un objet en interne - c'est-à-dire qu'elle s'appropriera l'argument. 2
Dans ces situations, nous avons le compromis (simplifié) suivant:
- Nous pouvons passer l'objet par référence, puis copier en interne.
- On peut passer l'objet par valeur.
"Passer par valeur" entraîne toujours la copie de l'objet, sauf si l'objet est une valeur r. Dans le cas d'une valeur r, l'objet peut être déplacé à la place, de sorte que le deuxième cas n'est plus soudainement «copier, puis déplacer» mais «déplacer, puis (potentiellement) se déplacer à nouveau».
Pour les gros objets qui implémentent des constructeurs de déplacement appropriés (tels que des vecteurs, des chaînes…), le deuxième cas est alors beaucoup plus efficace que le premier. Par conséquent, il est recommandé d' utiliser la fonction passer par valeur si la fonction prend possession de l'argument et si le type d'objet prend en charge un déplacement efficace .
Une note historique:
En fait, tout compilateur moderne devrait être capable de comprendre quand le passage par valeur est coûteux, et convertir implicitement l'appel pour utiliser une référence const si possible.
En théorie. En pratique, les compilateurs ne peuvent pas toujours changer cela sans casser l'interface binaire de la fonction. Dans certains cas spéciaux (lorsque la fonction est en ligne), la copie sera réellement éluée si le compilateur peut comprendre que l'objet d'origine ne sera pas modifié par les actions de la fonction.
Mais en général, le compilateur ne peut pas déterminer cela, et l'avènement de la sémantique des mouvements en C ++ a rendu cette optimisation beaucoup moins pertinente.
1 Par exemple dans Scott Meyers, Effective C ++ .
2 Cela est particulièrement vrai pour les constructeurs d'objets, qui peuvent prendre des arguments et les stocker en interne pour faire partie de l'état de l'objet construit.