2011-07-22 4 views
13

Y at-il raison de ne pas envoyer un paramètre comme const &, au lieu de la valeur, quand il ne sera pas modifié et aucune copie seront? Ma compréhension est qu'un const par paramètre de valeur est le même que sans le const (et ne se surchargera pas) donc il sera encore copié.Paramètres de fonction comme Const Référence

Je sais que c'est mieux pour les gros objets d'envoyer par const &, mais je ne sais pas où est la ligne pour cela. Ou si même de petits paramètres doivent être envoyés par la valeur si ils ne seront pas modifiés ou copiés. Note: J'ai essayé de chercher ceci mais le sujet est assez vague donc je n'ai pas trouvé de bonnes réponses, je m'excuse si cela a déjà été répondu (j'ai trouvé beaucoup de questions sur quand utiliser const quand utiliser const & mais pas à propos des avantages de la valeur par rapport à const & pour les objets qui ne sont pas manifestement de grande taille).

+2

vous trouverez peut-être cet article intéressant: http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/ – lccarrasco

+0

Exactement le type de chose que je cherchais merci! Les mots-clés sont si généraux qu'il était difficile pour moi de chercher. –

+0

@lccarrasco: Dave Abrahams parle de renvoyer des objets par valeur à l'intérieur des fonctions. La question concerne les paramètres d'entrée aux fonctions. Dans ce cas, l'OP doit passer des objets autres que les types natifs par référence const. – Praetorian

Répondre

22

Il y a généralement rien de mal à passer en lecture seule arguments comme référence const, et pour toute sorte de classe poids lourd qui est sûrement la façon la plus efficace de le faire.

Vous voudrez peut-être envisager de passer des types primitifs par copie, cependant, parce qu'il fait la référence pourrait effectivement engager plus coût que de copier simplement (par exemple, la copie serait tout simplement entrer dans un registre, alors qu'une référence peut être mis en œuvre avec pointeur, etc.).

En outre, vous pouvez probablement passer std::shared_ptr et itérateurs en valeur, ils sont faits pour cela. En ce qui concerne le passage par const-value, il s'agit d'un détail de mise en œuvre . Utilisez comme ceci:

// Declaration: 
int foo(int n, double d); // No "const"! Constness is not part of the interface. 

// Definition 
int foo(int n, const double d) // implementation detail 
{ 
    while (n--) { if (d > n) return n; } 
} 

Dans la mise en œuvre, vous pouvez ou ne pouvez pas choisir d'utiliser les variables d'arguments directement et les modifier (comme n), ou vous pouvez choisir de les traiter en lecture seule (comme d), et vous déclarez les arguments de manière appropriée.

+2

Je ne pensais pas que la copie du pointeur soit aussi chère ou pire pour les types primitifs, merci. –

+7

À noter, si vous passez un handle de comptage de référence (comme 'shared_ptr') par référence à travers une limite de fil, il devient alors impossible de décrémenter le nombre de références ** en toute sécurité - vous devez passer valeur dans ce cas. – spraff

+0

@spraff: Sympa. –

12

En règle générale, vous devez passer les types primitifs tels que les pointeurs, int, bool, float, double par valeur (non-const) et types d'objets tels que std::string, std::vector et des classes personnalisées par référence (const) . En tant qu'exception à cette règle, il existe des classes de poids léger spécialement conçues pour être transmises par valeur, telles que les pointeurs intelligents.

Passer une valeur par la valeur const, par ex. void foo(const double bar), n'a aucun sens - pourquoi ne devrait pas foo être autorisé à modifier sa copie de bar? Déclarer le paramètre comme const n'a aucune utilité ici.

Le fait de laisser des primitives par référence a également peu de sens. Dans les coulisses, lorsqu'un paramètre est passé par référence, un pointeur est passé par valeur. La copie d'un pointeur est généralement tout aussi coûteuse que la copie d'un type primitif (par exemple, int), et les paramètres de type const int& semblent plutôt étranges pour la plupart des programmeurs C++.

+0

J'accepterais deux réponses si je le pouvais! –

+3

Il y a des gens (je ne suis pas parmi eux) qui préfèrent en fait 'const double bar'. Ils disent qu'il empêche les causes de bugs en écrasant la valeur d'un paramètre dans une fonction. –

+0

Juste pour ajouter au commentaire @larsmans, l'utilisation de 'const double bar' vous empêche de faire accidentellement' if (bar = 5) 'au lieu de' == '. Mais c'est au prix de limiter ce que vous pouvez faire avec 'bar'. Votre algorithme peut exiger une modification sur place de 'bar' pour une raison quelconque. Je suppose que c'est juste un compromis entre flexibilité et sécurité. Cela dépend de combien vous voulez faire confiance au programmeur suivant! –

Questions connexes