web-dev-qa-db-fra.com

Référence vs pointeur

Quelle est la différence? Car ce:

int Value = 50;
int *pValue = &Value;

*pValue = 88;

et la version ref font la même chose:

int Value = 50;
int &rValue = Value;

rValue = 88;

Lequel est préférable d'utiliser? Merci.

13
Quest

Dans ce cas, ils sont équivalents.

Peu importe ce que vous utilisez, ni l'un ni l'autre ne sont "meilleurs".

Si vous voulez vraiment choisir entre eux, la référence est probablement plus idiomatique. En général, je m'en tiens aux références chaque fois que je le peux parce que mes TOC l'aiment bien: ils se sentent "plus étroits", ne peuvent pas être liés de nouveau (avec ou sans que vous le remarquiez) et ne nécessitent pas de déréférence pour obtenir la valeur.

Mais je ne suis au courant d'aucun consensus général sur la question pour des cas comme celui-ci.

Notez également que les deux ne peuvent pas compiler dans le même code si votre implémentation n'implémente pas les références avec des pointeurs, bien que je ne connaisse aucune implémentation de ce type, et vous ne remarqueriez pas la différence de toute façon.

20

Un pointeur est l'adresse de l'emplacement de la mémoire. Vous pouvez modifier la valeur de cette adresse pour qu'elle pointe vers différentes adresses de mémoire.

Une référence est un alias de la variable. Vous ne pouvez affecter cet alias que lors de la déclaration. Vous ne pouvez pas changer la variable dont la référence est un alias après avoir été déclarée.


Les affectations de pointeur suivantes ne sont pas possibles avec des références.

int a = 10;
int b = 20;

int* pInt = NULL; // A pointer pointing at nothing.
pInt = &a; // pInt now points at a
pInt = &b; // pInt now points at b

Quant à savoir lequel est le meilleur, tout dépend du contexte.

J'utilise des références pour les paramètres de méthode et de fonction.

void updateFoo(Foo& foo)

J'utilise des références à des objets complexes alias.

Foo& foo = bar.getBaz().getFoo(); // easy access to foo

J'utilise des pointeurs pour les objets alloués dynamiquement.

Foo* pFoo = new Foo();

J'utilise des pointeurs pour des choses pouvant indiquer différentes valeurs (y compris aucune valeur).

Foo* pFoo = NULL;

if (condition1)
    pFoo = &foo1;
else (condition2)
    pFoo = &foo2;

En règle générale, je sélectionne par défaut les références et utilise des pointeurs dans les endroits où les limitations de références posent des problèmes.

18
Jeffery Thomas

Les différences sont:

Référence est un alias d'objet et a la même adresse que l'objet.

int a;         //  address of   a : 0x0012AB
int &ref = a;  //  address of ref : 0x0012AB (the same)

Références doivent être initialisées :

int &ref = a; // GOOD, is compiling
int &ref;     // BAd, is not compiling

Le pointeur est une autre variable qui contient une adresse:

int a = 5;     //  address of a : 0x0012AB 
int *p = &a;   //  address of p : 0x0012AF (is different )

// value of a is 5
// value of p is 0x0012AB  (address of a)

Les pointeurs peuvent être NULL

int *p = NULL;
11
Dorin

Ma règle d'or est de privilégier l'utilisation d'une référence ou d'une référence const, sauf si un pointeur est requis.

La référence ne peut pas être réinstallée et elle est syntaxiquement plus propre. La référence vous garantit également que la référence n'est pas NULL.

Je peux également utiliser un pointeur pour plus de commodité lors de l'utilisation de tableaux.

3
justin

Je suis d’accord avec la réponse de Justin et j’aimerais la clarifier avec le plus petit exemple. 

Supposons que vous ne vous souveniez plus très bien de la syntaxe d’une bibliothèque géométrique d’images 2D: 

bool BooleanOr( const Bitmap & input1, const Bitmap & input2, Bitmap * output );

ou est-ce

bool BooleanOr( Bitmap * output, const Bitmap & input1, const Bitmap & input2 );

Si dans votre entreprise, tout le monde utilise des pointeurs pour les sorties et des références const pour les entrées, il est pratiquement impossible de se tromper: lorsque vous voyez des appels tels que

BooleanOr (thisBitmap, thatBitmap, & anotherBitmap);

vous connaissez immédiatement la syntaxe.

1
Michael

Excellentes réponses ici. Je voudrais souligner 2 usages spécifiques de références: -

Cas 1: lors de la mise en œuvre de operator[]. Cet opérateur doit généralement renvoyer quelque chose pouvant être utilisé comme cible d'une assignation Exemple: - 

vector<int> v(20);
v[1] = 5; //The target of the assignment is the return value of operator []

Ici, le operator [] renvoie une référence de l’élément à l’index spécifié dans la vector. Si operator [] avait été conçu pour renvoyer un pointeur à l’élément situé à l’index spécifié, il faudrait écrire la deuxième ligne de la manière suivante: -

*v[1] = 5

Cela donne maintenant à v le caractère de pointeur - ce qui n’est certainement pas le cas !! Ainsi, pour que le bon sens prévale - le operator [] renvoie un référence et non un pointeur à l'élément indexé dans le vecteur

Cas 2: aucune vérification null explicite n'est requise pour les références. Certaines réponses en ont déjà parlé - souhaitaient présenter l'avantage à l'aide d'un extrait de code: - 

void fun(const int& val)
{
  cout << val;
}

void fun(const int* val)
{
  if (val){ //Additional overhead with pointers
    cout << *val;
  }
}
1
Zakir