Contrairement à ce que l'on pense, il est possible d'avoir une référence NULLE.
int * p = NULL;
int & r = *p;
r = 1; // crash! (if you're lucky)
Certes, c'est beaucoup plus difficile à faire avec une référence, mais si vous y parvenez, vous vous arracherez les cheveux pour la trouver. Les références sont pas intrinsèquement sûr en C++ !
Techniquement, il s'agit d'une référence non valide et non une référence nulle. Le C++ ne prend pas en charge les références nulles en tant que concept, comme c'est le cas dans d'autres langages. Il existe également d'autres types de références non valides. Tous La référence non valide soulève le spectre d'une comportement non défini comme le ferait l'utilisation d'un pointeur non valide.
L'erreur réelle se situe au niveau du déréférencement du pointeur NULL, avant l'affectation à une référence. Mais je ne connais aucun compilateur qui génère des erreurs à cette condition - l'erreur se propage à un point plus éloigné dans le code. C'est ce qui rend ce problème si insidieux. La plupart du temps, si vous déréférencez un pointeur NULL, vous vous plantez directement à cet endroit et il ne faut pas beaucoup de débogage pour le découvrir.
Mon exemple ci-dessus est court et artificiel. Voici un exemple plus concret.
class MyClass
{
...
virtual void DoSomething(int,int,int,int,int);
};
void Foo(const MyClass & bar)
{
...
bar.DoSomething(i1,i2,i3,i4,i5); // crash occurs here due to memory access violation - obvious why?
}
MyClass * GetInstance()
{
if (somecondition)
return NULL;
...
}
MyClass * p = GetInstance();
Foo(*p);
Je tiens à rappeler que le seul moyen d'obtenir une référence nulle est d'utiliser un code malformé, et qu'une fois que vous l'avez, vous obtenez un comportement indéfini. Il nunca il est logique de vérifier si la référence est nulle ; par exemple, vous pouvez essayer if(&bar==NULL)...
mais le compilateur risque d'optimiser la déclaration pour qu'elle n'existe plus ! Une référence valide ne peut jamais être NULL, donc du point de vue du compilateur, la comparaison est toujours fausse, et il est libre d'éliminer l'élément if
comme du code mort - c'est l'essence même d'un comportement non défini.
Pour éviter les problèmes, il faut éviter de déréférencer un pointeur NULL pour créer une référence. Voici une méthode automatisée pour y parvenir.
template<typename T>
T& deref(T* p)
{
if (p == NULL)
throw std::invalid_argument(std::string("NULL reference"));
return *p;
}
MyClass * p = GetInstance();
Foo(deref(p));
Pour un examen plus ancien de ce problème par quelqu'un qui a de meilleures compétences en matière d'écriture, voir Références nulles de Jim Hyslop et Herb Sutter.
Pour un autre exemple des dangers du déréférencement d'un pointeur nul, voir Exposition d'un comportement indéfini lors du portage du code sur une autre plate-forme par Raymond Chen.
1 votes
Une référence locale (c'est-à-dire une référence qui ne se trouve pas dans une structure ou une classe) n'alloue pas nécessairement de l'espace de stockage. La différence entre sizeof(int &) et sizeof(struct { int &x ; }) permet de s'en rendre compte.
134 votes
Je pense que le point 2 devrait être "Un pointeur est autorisé à être NULL mais une référence ne l'est pas. Seul un code malformé peut créer une référence NULL et son comportement est indéfini."
31 votes
Les pointeurs sont un autre type d'objet et, comme tout objet en C++, ils peuvent être une variable. Les références, en revanche, ne sont jamais des objets, seulement variables.
29 votes
Cela se compile sans avertissement :
int &x = *(int*)0;
sur gcc. La référence peut en effet pointer vers NULL.7 votes
Je ne suis pas sûr d'être d'accord avec l'expression "les références sont du sucre syntaxique". Comment concevriez-vous les constructeurs de copies dans votre langage si vous n'aviez pas de références ?
1 votes
Nous pourrions probablement prendre l'adresse d'une référence, à l'instar de l'idiome adopté pour la mise en œuvre de l'opérateur d'affectation, c'est-à-dire
T& T::operator=(const T& rhs) { if (this == &rhs) return *this; ... }
.2 votes
Également utile lien
9 votes
Je ne me sens pas qualifié pour modifier la partie "clarifier une idée fausse" de cette question, mais je pense qu'il convient d'observer que si
int i
vit dans un registre pendant toute sa durée de vie, la référence n'est probablement pas un pointeur - elle peut simplement aliaser le même registre.29 votes
La référence est un alias de variable
4 votes
Les références ne sont pas un simple sucre syntaxique : elles sont TOUJOURS dans un état défini. C'est le compilateur qui s'en charge. Les pointeurs n'ont pas cette garantie.
26 votes
J'apprécie le fait que la toute première phrase soit totalement erronée. Les références ont leur propre sémantique.
9 votes
@Calmarius Non, ce n'est pas correct. Il s'agit d'une référence à ce qui se trouve à cet emplacement de la mémoire. La référence elle-même est valide. Accéder à ce qui s'y trouve est indéfini.
17 votes
@Calmarius Bien sûr, pour en arriver là, vous avez déréférencé un pointeur nul. qui est lui-même indéfini. . .
1 votes
Ces questions montrent que l'arithmétique des pointeurs est effectuée sur une référence ("
&obj + 5
"). Cela ne rompt-il pas les hypothèses d'aliasing, où le site d'appel suppose qu'une fonction appelée n'effectuera pas une telle arithmétique ? Cela signifie donc que l'arithmétique de référence est UB ?1 votes
Le pointeur stocke fondamentalement l'adresse de la personne qu'il pointe.
5 votes
Int *p = NULL ; int &r=*p ; référence pointant vers NULL ; if(r){} -> boOm ;)
1 votes
@QiangXu Non, cela prend l'adresse de la cible de la référence. Relisez-le : Une référence est un alias vers un autre objet. (En dehors de l'étape de création,) sa sémantique est entièrement identique à celle de l'utilisation du nom original de la cible.
1 votes
Je ne dirais pas que les références sont implémentées comme des pointeurs en C++, il s'agit de deux abstractions différentes pour les adresse d'un objet. Pensez au fonctionnement du matériel : dans le matériel, il n'y a pas de "pointeurs", il y a des registres, de la mémoire et des instructions qui opèrent sur les registres et la mémoire.
2 votes
J'aime imaginer que les variables sont des personnes à une fête, puis une pointeur est une personne qui se promène en pointant normalement son doigt sur quelqu'un d'autre et qui peut changer de personne. Dans certains cas, cette personne quitte la fête et ne peut plus être pointée du doigt (hors champ) ou assassinée (détruite, il s'agit d'une "guerre de l'argent"). mauvais ), à d'autres occasions, le pointeur peut être dirigé vers une nouvelle personne (valeur modifiée) ou vers l'étage (fixé à 0,
nullptr
etc.) En comparaison, un référence variable est un nouveau badge qu'une personne peut porter sur elle-même (et qu'un pointeur peut également utiliser).2 votes
a pointer and a reference both occupy the same amount of memory
- ce n'est pas correct. Un pointeur vers une fonction virtuelle peut occuper plus de mémoire qu'une référence.3 votes
Suis-je le seul à penser que les pointeurs sont plus faciles à lire et qu'ils clarifient davantage le code que les références ?
1 votes
Un point très important : le programmeur doit gérer la mémoire des pointeurs, mais pas celle des références.
2 votes
Un pointeur peut être nul, c'est-à-dire prendre une valeur qui ne pointe manifestement pas vers un objet ou une fonction valide. En revanche, une référence nulle ne peut exister dans un programme bien défini, car la seule façon de créer une telle référence serait de la lier à l'objet ou à la fonction obtenue par déréférencement d'un pointeur nul, ce qui entraîne un comportement indéfini.
0 votes
fbb-git.github.io/cppannotations/cppannotations/html/ Cela pourrait également être intéressant et peut-être aussi fbb-git.github.io/cppannotations/cppannotations/html/ - de The C++ Annotations qui est utile pour les programmeurs C - pour ce que cela vaut, c'est peut-être intéressant pour certains. Personnellement, j'ai eu plusieurs réactions très négatives à l'égard du C++ - l'aspect est pour moi inesthétique au plus haut point et ce n'est qu'un problème parmi beaucoup d'autres ... je ne pourrai donc pas ajouter plus que les liens mais peut-être qu'ils seront utiles ou intéressants pour certains.