Je peux écrire une fonction modélisée de cette façon ou de cette façon p> Je suppose que la deuxième option peut être plus optimale Comme il évite explicitement une copie, mais je soupçonne qu'il peut également échouer pour des types spécifiques t code> (par exemple, des foncteurs?).
Donc, quand devrait-il utiliser la première option et quand utiliser la seconde? Il y a aussi ce
boost :: call_traits
boost :: référence_wrapper code> qui étaient dans les réponses à mon
5 Réponses :
Y a-t-il une règle de base pour cela? p> blockQuote>
Les mêmes règles générales pour quand utiliser Pass par référence vs Pass par valeur s'appliquent. P>
Si vous attendez code> Toujours être un type numérique ou un type très bon marché pour copier, vous pouvez prendre l'argument par valeur. Si vous allez effectuer une copie de l'argument dans une variable locale dans la fonction de toute façon, vous devez le prendre par la valeur pour
Aidez le compilateur Elide des copies qui n'ont pas vraiment besoin d'être fabriquées. p> Sinon, prenez l'argument par référence. Dans le cas des types peu coûteux de copier, il peut être plus coûteux, mais pour d'autres types, ce sera plus rapide. Si vous trouvez qu'il s'agit d'un hotspot de performance, vous pouvez surcharger la fonction pour différents types d'arguments et faire la bonne chose pour chacun d'eux. P>
Donc, il n'y a pas de problèmes spécifiques à un modèle?
@ 7VIES: Pas vraiment; Le seul "problème" est que, au lieu d'avoir un seul type à penser, vous devez décider ce qui est logique pour le groupe de types avec lesquels le modèle sera utilisé.
@James McNellis: Je suppose que parfois vous ne pouvez pas décider cela, comme par exemple STL accepterait les foncteurs de valeur, tandis que l'on pourrait avoir un foncteur "lourdement étatique" et qui serait inefficace. Devrait-on utiliser que boost :: call_traits
@ 7VIES: Boost :: Call_Traits Code> ne vous aidera pas parce que
param_type code> est une référence constante pour tout type défini par l'utilisateur (et donc tous les types de classe). L'hypothèse dans la STL est que les objets de fonction sont bon marché pour copier; Si vous avez un objet de fonction coûteux à copier, la "solution droite" est de le rendre moins coûteux à copier, si possible, ou d'écrire une enveloppe qui le rend moins cher à copier.
@James McNellis: J'ai supposé (bien que jamais essayé), vous pouvez spécialiser ce trait de votre type s'il doit être transmis par la valeur.
@peterchen: Vous pouvez le spécialiser pleinement et cela pourrait être utile. Je n'ai jamais utilisé call_traits code>; Il semble juste que ce soit plus de problèmes que cela vaut la peine (c'est-à-dire s'il était vraiment utile, pourquoi pas les conteneurs C ++ 0x ont été mis à jour pour utiliser des techniques similaires?).
Il apparaît que C ++ 0x Les conteneurs semblent s'appuyer sur résorfir le pilfering par des références de rvalue pour réduire le coût des copies excessives. Je souhaite que l'une de ces méthodes n'aurait pas à fier des bibliothèques étendues - ou au moins ces bibliothèques pourraient générer des diagnostics spécifiques de la compilation.
En plus de ce que James McNellis a écrit, je veux juste ajouter que vous pouvez spécialiser votre modèle pour les types de référence ( par exemple comme celui-ci ) p>
Comme déjà mentionné, il n'y a pas de problèmes spécifiques à un modèle. P> boost :: traits code> a un trait de type qui sélectionne le type "meilleur", en fonction de T: p>
call_traits
p>
Typiquement compilateur ne peut pas déduire l'argument des temples dans ce cas (il s'agit d'un problème spécifique au modèle).
Je soupçonne qu'il peut également échouer pour certains types spécifiques p> blockQuote>
passe par référence-to-const est le seul mécanisme de passage qui "jamais" échoue. Il ne pose aucune exigence sur
t code>, il accepte à la fois des avalues et des avalues comme des arguments et permet des conversions implicites. P>
Tu ne réveilleras pas les morts, mais la tête un problème similaire et voici un exemple de code qui montre comment utiliser des traits de type C ++ 11S pour déduire si un paramètre doit être transmis par la valeur ou la référence:
#include <iostream> #include <type_traits> template<typename key_type> class example { using parameter_type = typename std::conditional<std::is_fundamental<key_type>::value, key_type, key_type&>::type; public: void function(parameter_type param) { if (std::is_reference<parameter_type>::value) { std::cout << "passed by reference" << std::endl; } else { std::cout << "passed by value" << std::endl; } } }; struct non_fundamental_type { int one; char * two; }; int main() { int one = 1; non_fundamental_type nft; example<int>().function(one); example<non_fundamental_type>().function(nft); return 0; }
Au risque de bêticulaire, je dois demander: comment pourrait-il échouer pour un foncteur?
@Beta: C'était une supposition aléatoire. Si quelqu'un pouvait expliquer dans quel cas cela peut réellement échouer, je serais intéressé.
Qu'est-ce que vous essayez d'atteindre? Cela dépend du code interne dans
f code>.
@David Rodríguez - Dribesas: C'est plus une question générale