6 votes

Passer par valeur ou référence, à un constructeur C++ qui doit stocker une copie ?

Un constructeur de valeurs C++ (implicite ou explicite) doit-il accepter son ou ses paramètres par valeur ou par référence à une constante, lorsqu'il doit stocker une copie de l'argument ou des arguments dans son objet, de l'une ou l'autre manière ?

Voici l'exemple le plus court auquel je peux penser :

struct foo {
    bar _b;
    foo(bar [const&] b) // pass by value or reference-to-const?
        : _b(b) { }
};

L'idée ici est que je veux minimiser les appels au constructeur de copie de bar quand un objet foo est créé, de n'importe laquelle des différentes manières dont un objet foo pourrait être créé.

Veuillez noter que je m'y connais un peu en élision de copie et en optimisation des valeurs de retour (nommées), et que j'ai lu les documents suivants "Vous voulez de la vitesse ? Passez par la valeur" Cependant, je ne pense pas que l'article aborde directement ce cas d'utilisation.

Editar: Je devrais être plus précis.

Supposons que je ne puisse pas connaître le sizeof(bar) ou si oui ou non bar est un type fondamental et intégré ( bar peut être un paramètre de modèle, et foo peut être un modèle de classe au lieu d'une classe). De même, ne supposez pas que foo Le constructeur de l'utilisateur peut être inlined (ou bar d'ailleurs). Je suppose que j'utilise au moins un compilateur qui implémente RVO.

Ce que j'aimerais, c'est qu'il y ait une possibilité (compte tenu des optimisations du compilateur) qu'un appel comme celui-ci n'invoque aucun appel à bar (même lors de l'exécution de la fonction de copie). _b(b) sur foo La liste d'initialisation de l'entreprise) :

foo f = function_that_creates_and_returns_a_bar_object_using_rvo();

Est-il possible (compte tenu de la norme C++98) que cela soit fait, et si oui, est-il plus ou moins probable que cela fonctionne si foo accepte son paramètre par référence-à-const plutôt que par valeur ?

1voto

Thanatos Points 13444

Je suppose que bar a un constructeur de copie normal de la forme bar(const bar &b)

Prenez une référence constante ici. bar Le constructeur de l'utilisateur prendra alors cette référence et effectuera la copie. Nombre total de copies : 1.

Si vous laissiez la référence désactivée, le compilateur ferait une copie de b, passerait la copie à foo qui le transmettra ensuite à l'utilisateur. bar et le copier.

0voto

rlbond Points 24215

Honnêtement, dans ce cas, la meilleure option est de faire en sorte que votre constructeur inline à condition que bar Le constructeur de l'utilisateur n'est pas lancé. Il suffit alors de passer par référence.

De plus, comme vous le soupçonniez, votre article ne s'applique pas ici.

-1voto

Patrick Points 3893

Maintenez un shared_pointer à bar dans votre classe et passez-le comme tel. De cette façon, vous n'appelez jamais le constructeur de copie :).

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