Existe-il des avantages de passer par un pointeur sur le passage par référence en C++?
Quels sont les 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 ont choisi passage d'arguments par des pointeurs 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);
- N'oubliez pas
new
créer un pointeur et les problèmes qui en découlent de la propriété.
Vous devez vous connecter pour publier un commentaire.
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:
func2 passes by reference
. Alors que je comprends que vous vouliez dire, il passe "par référence" à partir d'une perspective de haut niveau, mis en œuvre par le passage d'un pointeur à un code de niveau de point de vue, c'était très déroutant (voir stackoverflow.com/questions/13382356/...).func(int& a)
n'est pas valide C dans n'importe quelle version de la norme. Vous êtes probablement de la compilation de vos fichiers en C++ par accident.func(*NULL)
. Puis à l'intérieur de la fonction, test avecif (&x == NULL)
. Je suppose que cela semble laid, mais la différence entre pointeur et référence des paramètres est sucre syntaxique.Passage par pointeur
nothing
. Ceci peut être utilisé pour fournir des arguments optionnels.Passer par référence
string s = &str1 + &str2;
à l'aide de pointeurs.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.->
dans votre réponse...nous parlons pointeurs ici après tout. 😉Allen Holub est "Assez de Corde pour se Tirer dans le Pied", répertorie les 2 règles suivantes:
Il énumère plusieurs raisons pourquoi les références ont été ajoutées à C++:
const
références vous permettent de passer-par-valeur sémantique, tout en évitant une copieSon 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 que
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).
swap
fonction joue un rôle très important dans la copie d'échange à l'idiome, mais sans déclarer ses paramètres en tant que non-const références, il n'y a aucun moyen de faire ce qu'il a voulu faire. En utilisant les pointeurs ici sera pénible et les sauts de de son une exception sans promesse facilement.J'aime le raisonnement par un article du "cplusplus.com:"
Ce que je retiens, c'est que la grande différence entre le fait de choisir d'utiliser un pointeur ou une référence paramètre si la valeur NULL est une valeur acceptable. C'est tout.
Si la valeur est entrée, de sortie, modifiable etc. devrait être dans la documentation et /ou les commentaires au sujet de la fonction, après tout.
De précisions pour les précédents posts:
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 mauvais code, le compiler & exécuter: (Au moins sous mon compilateur.)
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=().
Soudainement il y a un monde de différence entre foo(BAR) et foo(BAR & 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 revisiter 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 pratiquement:
*i
, votre programme a un comportement indéfini. Par exemple, le compilateur peut voir ce code et d'assumer "OK, ce code a un comportement indéfini dans tous les chemins de code, de sorte que l'ensemble de cette fonction doit être inaccessible." Ensuite, il va supposer que toutes les branches qui conduisent à cette fonction ne sont pas prises. C'est régulièrement effectuée optimisation.test(*i)
d'instruction n' pas déréférencer NULL. NUL ne serait déréférencé si la fonction consulté le paramètrea
sans&
de l'opérateur. Peut-être que c'est supposé être impossible de passer la valeur NULL juste pour éviter le besoin d'écrire plus l'épreuve des balles code.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.