275 votes

Existe-il des avantages de passer par un pointeur sur le passage par référence en C++?

Existe-il des avantages de passer par un pointeur sur le passage par référence en C++?

Dernièrement, j'ai vu un certain nombre d'exemples qui passent de l'un pointeur au lieu de passer par référence. Existe-il des avantages à le faire?

Exemple:

func(SPRITE *x);

avec un appel de

func(&mySprite);

vs

func(SPRITE &x);

avec un appel de

func(mySprite);

269voto

Passage par pointeur

  • L'appelant doit prendre l'adresse -> pas transparent
  • Une valeur 0 peut être fourni pour signifier nothing. Ceci peut être utilisé pour fournir des arguments optionnels.

Passage par référence

  • L'appelant transmet simplement l'objet -> transparent. Doit être utilisé pour la surcharge d'opérateur, comme la surcharge pour les types pointeur n'est pas possible (les pointeurs sont builtin types). Si vous ne pouvez pas faire string s = &str1 + &str2; en utilisant les pointeurs.
  • Pas de 0 de valeurs possibles -> fonction Appelée n'a pas à vérifier pour eux
  • Référence const accepte aussi temporaires: void f(const T& t); ... f(T(a, b, c));, les pointeurs ne peut pas être utilisé comme cela, puisque vous ne pouvez pas prendre l'adresse d'une mesure temporaire.
  • Dernier mais non le moindre, les références sont plus faciles à utiliser -> moins de risques de bugs.

248voto

Adam Rosenfield Points 176408

Un pointeur peut recevoir un paramètre NULL, un paramètre de référence ne peut pas. Si il y a toujours une chance que vous pourriez désirer pour passer à "sans objet", puis utiliser un pointeur au lieu d'une référence.

Aussi, le passage par pointeur vous permet explicitement de le voir sur le site d'appel si l'objet est passé par valeur ou par référence:

// Is mySprite passed by value or by reference?  You can't tell 
// without looking at the definition of func()
func(mySprite);

// func2 passes "by pointer" - no need to look up function definition
func2(&mySprite);

69voto

Michael Burr Points 181287

Allen Holub "Assez de Corde pour se Tirer dans le Pied", répertorie les 2 règles suivantes:

120. Reference arguments should always be `const`
121. Never use references as outputs, use pointers

Il énumère plusieurs raisons pourquoi les références ont été ajoutées à C++:

  • ils sont nécessaires à la définition de la copie des constructeurs
  • ils sont nécessaires pour la surcharge de l'opérateur
  • const références vous permettent de passer-par-valeur sémantique, tout en évitant une copie

Son point principal est que les références ne doivent pas être utilisés en tant que "production" des paramètres, car sur le site d'appel il n'y a aucune indication à savoir si le paramètre est une référence ou une valeur de paramètre. Donc sa règle est de n'utiliser const des références comme arguments.

Personnellement, je pense que c'est une bonne règle de pouce comme il le rend plus clair lorsqu'un paramètre est un paramètre de sortie ou pas. Cependant, alors que j'ai personnellement d'accord avec cette en général, je ne me laisser influencer par les opinions des autres sur mon équipe si ils font valoir pour les paramètres de sortie comme des références (des développeurs comme énormément).

10voto

Mr.Ree Points 5112

Précisions pour les précédents posts:


Les références sont PAS une garantie d'un pointeur non null. (Si l'on a souvent les traiter comme tels.)

Alors que terrifiant mauvais code, comme vous derrière le bûcher du mauvais code, le compiler & exécuter: (Au moins sous mon compilateur.)

bool test( int & a)
{
  return (&a) == (int *) NULL;
}

int
main()
{
  int * i = (int *)NULL;
  cout << ( test(*i) ) << endl;
};


Le vrai problème que j'ai avec les références se trouve avec les autres programmeurs, désormais appelé IDIOTS, qui allouer, dans le constructeur, de libérer dans le destructeur, et ne parviennent pas à fournir un constructeur de copie ou de l'opérateur=().

Soudain, il y a un monde de différence entre les foo(BAR) et foo(BAR et bar). (Automatique bit à bit de l'opération de copie est appelé. Libération de la mémoire dans le destructeur est appelé deux fois.)

Heureusement, les compilateurs modernes pour reprendre le double de désallocation de la même pointeur. Il y a 15 ans, ils n'ont pas. (Gcc/g++, l'utilisation *setenv MALLOC_CHECK_ 0* de revoir les anciennes façons de faire.) Elle résulte, en vertu de l'DÉC UNIX, dans le même espace mémoire alloué à deux objets différents. Beaucoup de débogage plaisir...


Plus concrètement:

  • Références cacher que vous modifiez les données stockées ailleurs.
  • Il est facile de confondre une Référence à un objet Copié.
  • Les pointeurs à l'évidence!

3voto

Brian Points 2013

Pas vraiment. En interne, le passage par référence est effectuée par essentiellement en passant l'adresse de l'objet référencé. Donc, il ya vraiment pas de gains d'efficacité en passant un pointeur.

Le passage par référence a un avantage, cependant. Vous êtes assuré de disposer d'une instance d'un objet/type qui est passé en. Si vous passez un pointeur, alors vous courez le risque de recevoir un pointeur NULL. En utilisant par référence, vous poussez un implicite NULL check-up d'un niveau à l'appelant de votre fonction.

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