Je sais que les références sont un sucre syntaxique, pour que le code soit plus facile à lire et à écrire.
Mais quelles sont les différences ?
Résumé des réponses et des liens ci-dessous :
NULL
), alors qu'une référence se réfère toujours à un objet.&obj + 5
).Pour clarifier un malentendu :
La norme C++ est très prudente pour éviter de dicter comment un compilateur peut implémenter les références, mais tous les compilateurs C++ implémentent les références comme des pointeurs. les références comme des pointeurs. C'est-à-dire qu'une déclaration telle que :
int &ri = i ;
si elle n’est pas entièrement optimisée, alloue la même quantité de stockage qu'un pointeur, et place l'adresse de
i
dans ce stockage.
***Ainsi, un pointeur et une référence utilisent tous deux la même quantité de mémoire.
En règle générale,
Lecture intéressante :
[1] : http://yosefk.com/c++fqa/ref.html [2] : http://www.embedded.com/electronics-blogs/programming-pointers/4023307/References-vs-Pointers [3] : http://www.embedded.com/electronics-blogs/programming-pointers/4024641/An-Introduction-to-References [4] : http://www.embedded.com/electronics-blogs/programming-pointers/4023290/References-and-const
Un pointeur peut être réaffecté :
int x = 5 ;
int y = 6 ;
int *p ;
p = &x ;
p = &y ;
*p = 10 ;
assert(x == 5) ;
assert(y == 10) ;
Une référence ne peut pas, et doit être assignée à l'initialisation :
int x = 5 ;
int y = 6 ;
int &r = x ;
Un pointeur a sa propre adresse mémoire et sa propre taille sur la pile (4 octets sur x86), alors qu'une référence partage la même adresse mémoire (avec la variable originale) mais prend également de l'espace sur la pile. Puisqu'une référence a la même adresse que la variable originale elle-même, il est prudent de considérer une référence comme un autre nom pour la même variable. Remarque : ce vers quoi pointe un pointeur peut se trouver sur la pile ou le tas. Idem pour une référence. Mon affirmation dans cette déclaration n'est pas qu'un pointeur doit pointer vers la pile. Un pointeur est simplement une variable qui contient une adresse mémoire. Cette variable se trouve sur la pile. Puisqu'une référence a son propre espace sur la pile, et puisque l'adresse est la même que la variable qu'elle référence. Plus d'informations sur [stack vs heap][1]. Cela implique qu'il existe une adresse réelle d'une référence que le compilateur ne vous dira pas.
int x = 0 ;
int &r = x ;
int *p = &x ;
int *p2 = &r ;
assert(p == p2) ;
Vous pouvez avoir des pointeurs vers des pointeurs vers des pointeurs offrant des niveaux supplémentaires d'indirection. Alors que les références n'offrent qu'un seul niveau d'indirection.
int x = 0 ;
int y = 0 ;
int *p = &x ;
int *q = &y ;
int **pp = &p ;
pp = &q;//*pp = q
**pp = 4 ;
assert(y == 4) ;
assert(x == 0) ;
Le pointeur peut être assigné nullptr
directement, alors que la référence ne le peut pas. Si vous essayez assez fort, et que vous savez comment, vous pouvez rendre l'adresse d'une référence nullptr
. De même, si vous faites des efforts, vous pouvez avoir une référence à un pointeur, et alors cette référence peut contenir nullptr
.
int *p = nullptr ;
int &r = nullptr ; <--- erreur de compilation
int &r = *p ; <--- probablement pas d'erreur de compilation, surtout si le nullptr est caché derrière un appel de fonction, pourtant il fait référence à un int inexistant à l'adresse 0.
Les pointeurs peuvent itérer sur un tableau, vous pouvez utiliser ++
pour aller à l'élément suivant sur lequel pointe un pointeur, et + 4
pour aller au 5ème élément. Et ce, quelle que soit la taille de l'objet sur lequel pointe le pointeur.
Un pointeur doit être déréférencé avec *
pour accéder à l'emplacement mémoire qu'il pointe, alors qu'une référence peut être utilisée directement. Un pointeur vers une classe/structure utilise ->
pour accéder à ses membres alors qu'une référence utilise un .
.
Un pointeur est une variable qui contient une adresse mémoire. Indépendamment de la façon dont une référence est implémentée, une référence a la même adresse mémoire que l'élément qu'elle référence.
Les références ne peuvent pas être insérées dans un tableau, alors que les pointeurs peuvent l'être (Mentionné par l'utilisateur @litb)
Les références constantes peuvent être liées à des temporaires. Les pointeurs ne le peuvent pas (pas sans une certaine indirection) :
const int &x = int(12) ; //légal C++
int *y = &int(12) ; //illégal de déréférencer un temporaire.
Cela rend const&
plus sûr pour l'utilisation dans les listes d'arguments et ainsi de suite.
[1] : https://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap#79936
En dehors du sucre syntaxique, une référence est un pointeur const
(non pointeur vers un const
). Vous devez établir ce à quoi il se réfère lorsque vous déclarez la variable de référence, et vous ne pouvez pas le changer plus tard.
Mise à jour : maintenant que j'y pense un peu plus, il y a une différence importante.
La cible d'un pointeur const peut être remplacée en prenant son adresse et en utilisant un const cast.
La cible d'une référence ne peut être remplacée par aucun moyen autre que l'UB.
Ceci devrait permettre au compilateur de faire plus d'optimisation sur une référence.