Quelle serait la meilleure pratique pour attribuer à une fonction la variable d'origine avec laquelle travailler:
unsigned long x = 4;
void func1(unsigned long& val) {
val = 5;
}
func1(x);
ou:
void func2(unsigned long* val) {
*val = 5;
}
func2(&x);
IOW: Y a-t-il une raison de choisir l'un plutôt que l'autre?
Réponses:
Ma règle d'or est la suivante:
Utilisez des pointeurs si vous souhaitez effectuer une arithmétique de pointeur avec eux (par exemple, incrémenter l'adresse du pointeur pour parcourir un tableau) ou si vous devez passer un pointeur NULL.
Sinon, utilisez des références.
la source
Base* b = new Derived()
)? Cela semble être un cas qui ne peut être traité sans pointeurs.Je pense vraiment que vous bénéficierez de l'établissement des directives de codage des fonctions suivantes:
Comme dans tous les autres endroits, soyez toujours
const
correct.const
spécificateur.Ne passez une valeur par pointeur que si la valeur 0 / NULL est une entrée valide dans le contexte actuel.
Justification 1: En tant qu'appelant , vous voyez que tout ce que vous passez doit être dans un état utilisable.
Justification 2: Comme appelé , vous savez que tout ce qui entre est dans un état utilisable. Par conséquent, aucune vérification NULL ou gestion des erreurs ne doit être effectuée pour cette valeur.
Justification 3: Les rationnels 1 et 2 seront appliquées par le compilateur . Attrapez toujours les erreurs au moment de la compilation si vous le pouvez.
Si un argument de fonction est une valeur de sortie, passez-le par référence.
Choisissez "passer par valeur" sur "passer par référence const" uniquement si la valeur est un POD ( Plain old Datastructure ) ou assez petit (en mémoire) ou d'une autre manière assez bon marché (en temps) pour copier.
la source
std::vector<>
.Cela finit finalement par être subjectif. La discussion jusqu'à présent est utile, mais je ne pense pas qu'il y ait de réponse correcte ou décisive à cela. Beaucoup dépendra des directives de style et de vos besoins à l'époque.
Bien qu'il existe différentes capacités (que quelque chose puisse être NULL ou non) avec un pointeur, la plus grande différence pratique pour un paramètre de sortie est purement syntaxique. Le Guide de style C ++ de Google ( https://google.github.io/styleguide/cppguide.html#Reference_Arguments ), par exemple, n'impose que des pointeurs pour les paramètres de sortie et n'autorise que les références const. Le raisonnement est celui de la lisibilité: quelque chose avec une syntaxe de valeur ne devrait pas avoir de signification sémantique de pointeur. Je ne dis pas que c'est nécessairement vrai ou faux, mais je pense que le point ici est que c'est une question de style, pas de correction.
la source
Vous devez passer un pointeur si vous souhaitez modifier la valeur de la variable. Même si le passage technique d'une référence ou d'un pointeur est le même, le passage d'un pointeur dans votre cas d'utilisation est plus lisible car il "annonce" le fait que la valeur sera modifiée par la fonction.
la source
const
ou nonconst
, mais vous pouvez voir si le paramètre a passé ala&x
vsx
, et utiliser cette convension pour coder si le paramètre est susceptible d'être modifié. (Cela dit, il y a des moments où vous voudrez passer unconst
pointeur, donc la convension n'est qu'un indice. ....)Si vous avez un paramètre où vous devrez peut-être indiquer l'absence de valeur, il est courant de faire du paramètre une valeur de pointeur et de passer NULL.
Une meilleure solution dans la plupart des cas (du point de vue de la sécurité) consiste à utiliser boost :: facultatif . Cela vous permet de passer des valeurs facultatives par référence et également comme valeur de retour.
la source
Utilisez une référence quand vous le pouvez, utilisez un pointeur quand vous le devez. D'après la FAQ C ++: "Quand dois-je utiliser des références et quand dois-je utiliser des pointeurs?"
la source
Pointeurs
Un pointeur qui ne pointe pas actuellement vers un emplacement de mémoire valide reçoit la valeur null (qui est zéro)
Le & est un opérateur unaire qui renvoie l'adresse mémoire de son opérande.
L'opérateur de déréférencement (*) est utilisé pour accéder à la valeur stockée dans la variable vers laquelle pointe le pointeur.
Référence
Une référence (&) est comme un alias vers une variable existante.
Une référence (&) est comme un pointeur constant qui est automatiquement déréférencé.
Il est généralement utilisé pour les listes d'arguments de fonction et les valeurs de retour de fonction.
Une référence doit être initialisée lors de sa création.
Une fois qu'une référence est initialisée à un objet, elle ne peut pas être modifiée pour faire référence à un autre objet.
Vous ne pouvez pas avoir de références NULL.
Une référence const peut faire référence à un const int. Cela se fait avec une variable temporaire avec la valeur de la const
la source
Une référence est un pointeur implicite. Fondamentalement, vous pouvez modifier la valeur vers laquelle les points de référence sont définis, mais vous ne pouvez pas modifier la référence pour pointer vers autre chose. Donc, mon 2 cents est que si vous voulez seulement changer la valeur d'un paramètre, passez-le comme référence mais si vous devez changer le paramètre pour pointer vers un objet différent, passez-le en utilisant un pointeur.
la source
Considérez le mot clé out de C #. Le compilateur requiert que l'appelant d'une méthode applique le mot clé out à tous les arguments out, même s'il sait déjà s'ils le sont. Ceci est destiné à améliorer la lisibilité. Bien qu'avec les IDE modernes, je suis enclin à penser que c'est un travail de mise en évidence syntaxique (ou sémantique).
la source
Passez par référence const sauf s'il y a une raison pour laquelle vous souhaitez modifier / conserver le contenu que vous transmettez.
Ce sera la méthode la plus efficace dans la plupart des cas.
Assurez-vous que vous utilisez const sur chaque paramètre que vous ne souhaitez pas modifier, car cela vous protège non seulement de faire quelque chose de stupide dans la fonction, mais il donne une bonne indication aux autres utilisateurs de ce que la fonction fait aux valeurs transmises. Cela comprend la création d'un pointeur const lorsque vous ne souhaitez modifier que ce qui est indiqué ...
la source
Pointeurs:
nullptr
(ouNULL
).&
si votre type n'est pas un pointeur lui-même, ce qui signifie explicitement que vous modifiez votre objet.Références:
&
. Ceci est parfois considéré comme mauvais car vous devez aller à l'implémentation de la fonction pour voir si votre paramètre est modifié.la source
Une référence est similaire à un pointeur, sauf que vous n'avez pas besoin d'utiliser un préfixe ∗ pour accéder à la valeur référencée par la référence. De même, il n'est pas possible de faire référence à un objet différent après son initialisation.
Les références sont particulièrement utiles pour spécifier des arguments de fonction.
pour plus d'informations, voir "A Tour of C ++" de "Bjarne Stroustrup" (2014) Pages 11-12
la source