J'ai vu de nombreux arguments que l'utilisation d'une valeur de retour est préférable à des paramètres out. Je suis convaincu des raisons pour lesquelles je dois les éviter, mais je ne suis pas sûr de savoir si je suis dans une situation où c'est inévitable.Comment éviter les paramètres?
Première partie de ma question est: Quels sont certains de vos moyens préférés/communs de se déplacer en utilisant un paramètre out? Stuff le long des lignes: Man, dans les critiques par les pairs, je vois toujours d'autres programmeurs le font quand ils auraient pu le faire facilement de cette façon.
Deuxième partie de ma question traite de certains cas spécifiques que j'ai rencontrés où je voudrais éviter un paramètre out mais ne peut pas penser à un moyen propre de le faire.
Exemple 1: J'ai une classe avec une copie coûteuse que je voudrais éviter. Le travail peut être fait sur l'objet et cela construit l'objet pour être coûteux à copier. Le travail de construction des données n'est pas non plus trivial non plus. Actuellement, je vais passer cet objet dans une fonction qui va modifier l'état de l'objet. Pour moi, c'est préférable à la nouveauté de l'objet interne à la fonction de travail et de le renvoyer, car cela me permet de garder les choses sur la pile.
class ExpensiveCopy //Defines some interface I can't change.
{
public:
ExpensiveCopy(const ExpensiveCopy toCopy){ /*Ouch! This hurts.*/ };
ExpensiveCopy& operator=(const ExpensiveCopy& toCopy){/*Ouch! This hurts.*/};
void addToData(SomeData);
SomeData getData();
}
class B
{
public:
static void doWork(ExpensiveCopy& ec_out, int someParam);
//or
// Your Function Here.
}
En utilisant ma fonction, je me appelle code comme ceci:
const int SOME_PARAM = 5;
ExpensiveCopy toModify;
B::doWork(toModify, SOME_PARAM);
J'aimerais avoir quelque chose comme ceci:
ExpensiveCopy theResult = B::doWork(SOME_PARAM);
Mais je ne sais pas si cela est possible.
Deuxième exemple: J'ai un tableau d'objets. Les objets dans le tableau sont un type complexe, et j'ai besoin de travailler sur chaque élément, travail que je voudrais garder séparé de la boucle principale qui accède à chaque élément. Le code ressemble à ceci:
std::vector<ComplexType> theCollection;
for(int index = 0; index < theCollection.size(); ++index)
{
doWork(theCollection[index]);
}
void doWork(ComplexType& ct_out)
{
//Do work on the individual element.
}
Des suggestions sur la façon de gérer certaines de ces situations? Je travaille principalement en C++, mais je suis intéressé de voir si d'autres langages facilitent une installation plus facile. J'ai rencontré RVO comme une solution possible, mais j'ai besoin d'en lire plus à ce sujet et cela ressemble à une fonctionnalité spécifique au compilateur.
La sémantique d'un paramètre de référence non-const est qu'il sera (peut-être) modifié dans la fonction. Si vous n'alliez pas le changer, vous le passeriez comme référence de const, après tout. – Bill
* "mais je suis intéressé de voir si d'autres langages facilitent une installation plus simple" * - les langages comme Java et C# n'ont tout simplement pas ce problème car ils donnent toujours des références aux objets qui les entourent. –
Merveilleuses réponses de tous. J'avais le sentiment que dans mes exemples précis, il n'y aurait pas beaucoup d'autres options.J'ai vu des messages sur le SO de la part de personnes qui sont si catégoriques sur la façon dont ils évitent les paramètres à tout prix. J'espérais que peut-être l'un d'entre eux pourrait expliquer comment ils réalisent un tel exploit. Comme pour RVO, je suis quelque peu hésitant à utiliser des fonctionnalités spécifiques au compilateur, car il serait difficile d'expliquer à mes supérieurs pourquoi je dois redessiner la moitié de mon code car il ne fonctionne plus en raison d'une fonctionnalité manquante suite à un changement de compilateur/mise à niveau. –