9
votes

Pourquoi n'y a-t-il pas de "référence null" en C ++?

Je lisais la FAQ C ++ - " 8.6 - Quand Devrais-je utiliser des références et quand devrais-je utiliser des pointeurs? "et en particulier cette déclaration:

Utilisez des références lorsque vous le pouvez, et des pointeurs lorsque vous devez.

...

L'exception à ce qui précède est la suivante: le paramètre ou la valeur de retour d'une fonction nécessite une référence "Sentinel" - une référence qui ne fait pas référence à un objet. Ceci est généralement meilleur fait en retournant / en prenant un pointeur et en donnant au pointeur NULL cette signification particulière (les références doivent toujours être des objets alias, pas un pointeur nul déréférencé).

De ce que j'ai vu, la nécessité d'une référence "sentinelle" est en effet souvent la raison d'utiliser des pointeurs au lieu de références. Ce que je me demande, c'est que c ++ n'a pas une "valeur null" spéciale pour les références? Il semble que cela rendrait les pointeurs presque inutiles, ce qui résoudrait de nombreux problèmes.

Alors pourquoi ne pas faire partie de la spécification de langue?

EDIT:

Je ne suis pas sûr que ma question soit claire - je suppose que je ne demande pas littéralement des références nulles. Le plus souvent, je lis cela en C ++ "La référence est l'objet". Et, dans la plupart des langages de l'OOP, des objets peuvent être nuls - Pascal, C #, Java, JavaScript, PHP, etc. dans tous ceux-ci, vous pouvez faire ToOObject = null ou TOOOObject: = nul . En fait, Pascal prend également en charge les pointeurs mais permet toujours aux objets d'être nil , car il a son utilisation. Alors, pourquoi C ++ est-il spécial et n'a pas d'objet nul? Était-ce juste une phrase ou une décision réelle?


3 commentaires

Priez dire comment cela supprimerait le besoin de pointeurs?


@nathanwhite car alors les références seraient du sucre syntaxique pour les pointeurs, vraisemblablement, pouvant être utilisés chaque fois que les pointeurs sont. Lequel, imo, supprimerait complètement certains des avantages des références.


Lire Pourquoi C ++ a-t-il à la fois des pointeurs et des références? et C ++: référence null .


5 Réponses :


0
votes

Référence doit faire référence à quelque chose, donc, la référence null n'est pas disponible.
C n'a pas de références et nous ne pouvons utiliser que des pointeurs dans cette langue, il s'agit donc de la compatibilité avec la langue C


0 commentaires

14
votes

Parce qu'une référence porte la sémantique qu'elle pointe vers une adresse de mémoire valide qui ne change jamais; C'est-à-dire que la déséroférance est sûre / définie et donc aucune vérification nulle n'est requise. Les références ne peuvent pas être réaffectées par la conception.

Vous utilisez un pointeur lorsque le VAR peut être NULL et que le code client doit gérer ce cas. Vous utilisez une référence lorsque vous pouvez garantir une adresse mémoire valide / initialisée.

Un exemple d'utilisation des pointeurs est en tant que membre d'une classe pour stocker une "référence" à une instance qui pourrait ne pas être connue ni capable d'être initialisée au moment de la construction de classe. Cependant, les références des membres doivent être initialisées au temps de construction (via des listes d'initialisateur) et leur affectation ne peut pas être différée.

Si vous autorisez une référence null, il n'est alors pas différent d'un pointeur en plus de la syntaxe (les mêmes chèques nuls devraient avoir lieu.)

mise à jour:

"Et, dans la plupart des langages de l'OOP, les objets peuvent être nuls - Pascal, C #, Java, JavaScript, PHP, etc. [...] Pourquoi est-ce que C ++ est spécial et n'a pas d'objet null? juste une phrase ou une décision réelle? "

Je pense que vous êtes un peu confus à ce sujet. Java et C #, etc., etc. peuvent donner l'impression de "Objets NULL" , mais ces références d'objet sont plus ou moins comme un pointeur C ++ avec syntaxe plus simple, instrumentation GC et jeux d'exception. Dans ces langues si vous opérez sur un "objet nul", vous obtiendrez une sorte d'exception comme NullReferenceException (C #). Enfer, en Java, c'est appelé une NullpointException .

Vous devez vérifier null avant de pouvoir les utiliser en toute sécurité. Comme des pointeurs similaires tels que c ++ (sauf dans la plupart des langages gérés, les pointeurs sont initialisés à NULL par défaut, alors qu'en C ++, il est généralement à vous de vous occuper de la définition de la valeur initiale du pointeur (sinon indéfini / quelle que soit la mémoire indéfinie / quelle que soit la mémoire ou quelle que soit sa mémoire déjà indéfinie)). < / p>

La vue C ++ est d'avoir le choix, et donc être verbeuse:

  • Utilisez un pointeur ordinaire pour faire la façon dont vous voulez, vérifiez NULL si nécessaire.
  • Utilisez des références qui ont une validité forcée de compilateur sémantique / contrainte.
  • Roulez vos propres pointeurs intelligents qui comptaient de la comptabilité et qui se comportaient selon lesquelles vous les souhaitez.
  • en utilisant des pointeurs de vide (prudemment!) Pour faire référence à un bloc de mémoire non typable si nécessaire.

2 commentaires

NIT: Un pointeur nul et un pointeur non initialisé sont deux choses différentes. Un pointeur non initialisé ne peut pas être détecté, au moins pas de manière fiable, car il pourrait pointer n'importe où, y compris à un objet valide.


@hvd merci et corrigé. Par inaitalisé, je voulais vraiment dire null. Ajout d'une section sur CTORS pour illustrer une utilisation distinctive des pointeurs.



1
votes

La référence par définition doit être associée à une autre variable ou objet. Donc, une sorte de référence vide ou nulle de violents le but de l'existence.

Techniquement, cela signifierait que vous commencez par une référence nulle, puis l'affectez-la à une variable ou peut-être que cette dernière réaffecte à une autre variable. Ce n'est tout simplement pas quelle référence a été censée être créée.

Il existe plusieurs autres utilisations des pointeurs que la référence peut simplement ne pas répliquer. Par exemple, faire référence à un gros morceau de données complexes (une séquence d'octets) avec une petite quantité de mémoire à l'aide d'un pointeur et transmettant aussi souvent que nécessaire en ne dépensant que 8 octets ou donc pour le pointeur. Vous ne pouvez pas faire cela avec une référence sans gaspiller de la mémoire égale.

La référence serait toujours liée à un type, ce qui n'est pas le cas avec le pointeur.


2 commentaires

Les 2 premiers paragraphes sont corrects. Le dernier n'a pas de sens.


J'ai certainement eu un cas d'utilisation à l'esprit qui peut avoir été élaboré correctement. Mais ci-dessus commentaire sans élaboration ni opinion, simplement "n'a pas de sens" est encore plus inutile et ne porte aucune pondération



6
votes

Veuillez consulter les différences entre les pointeurs et les références - tandis que la norme laisse l'ouverture de la manière dont les références sont implémentées, elles sont actuellement toujours implémentées comme des pointeurs.

ce qui signifie que la principale différence entre eux est a) la sémantique B) des pointeurs peuvent être réinstallés c) les pointeurs peuvent être nuls.

La réponse courte est donc, cela a été fait exprès. Lorsque vous êtes en tant que programmeur, voir une référence, vous devez savoir que a) cette référence est remplie B) il ne changera pas (et c) que vous pouvez l'utiliser avec la même sémantique qu'un objet).

La norme permettrait à une référence nulle, vous devrez toujours vérifier NULL avant d'utiliser une référence, qui n'a pas été recherchée.

EDIT:

Concernant votre édition, je suppose que la confusion ici pourrait découler du fait que la plupart des langues de OO plus simples cachent ce qui se passe. Prendre l'exemple de Java, alors qu'il semble que vous ayez des objets NULL, vous ne pouvez vraiment pas les affecter, ce qui ne peut vraiment pas - ce qui se passe vraiment est que Java n'a que des pointeurs et peut affecter des valeurs nulles à ces indicateurs. Comme il est impossible d'avoir des objets directement dans Java, ils éloignent la sémantique du pointeur et traitent le pointeur comme objet. C ++ est tout simplement plus puissante - et une erreur d'erreur (l'enthousiaste de Java dirait que les instances de la classe d'utilisateurs de pile ne sont pas requises et la décision de ne pas les avoir à Java a été poussée à réduire la complexité et à utiliser Java à utiliser). Cela s'ensuit aussi que, puisque Java n'a pas d'objets, il n'a pas de références. Ce qui ne vous aide vraiment pas, cependant, est que Java appelle quelle personne C ++ appellerait une valeur de passage d'un pointeur une référence de passage.


3 commentaires

J'ai mis à jour ma question. Comment allez-vous expliquer que presque toutes les langues OO autorisent null références, mais c ++ ne le fait pas? Dans toutes ces autres langues, vous n'avez pas toujours besoin de vérifier NULL, cela dépend complètement du contexte.


Je ne sais pas que beaucoup de langues OO, mais pour ceux que je faisais je suis en désaccord. Java n'a même pas de références, Java n'a que des pointeurs (par exemple, peut être NULL, peut être réinstallé), bien que une syntaxe différente. L'une des raisons pour lesquelles Java n'a pas de références, c'est que Java n'a pas non plus de variables de pile (à court de types intégrés) - tout est tas, chaque variable est un pointeur, peut donc être null, aucune mémoire de pile, pas besoin de les références. Il en va de même pour VBA. C'est à peu près autant de langues oo que je sache.


Considérer par exemple Un cas d'utilisation typique de références en C ++: vous avez des variables allouées de grandes piles et souhaitez les transmettre par référence au lieu de la valeur. Ici, vous devez utiliser de vraies références C ++ et sont juste de le faire, car ils doivent être non nuls et ne changeront pas. En Java, vous ne pouvez pas avoir de variables de pile. L'environnement d'appel n'aura donc toujours que des pointeurs de toute façon, de sorte que vous n'avez pas besoin d'une construction pour réussir. Il y a souvent une confusion - ce que les gens de Java appellent "Pass par référence" C ++ Les personnes devraient vraiment appeler "Pass par pointeur".



1
votes

Une référence C ++ n'est pas une référence dans le sens où la plupart des autres langues utilisent le terme; C'est plus comme un alias . L'utilisation d'une référence C ++ n'implique pas "la déséroférance" de la même manière que vous avez une déréférence un pointeur; il est l'objet qui lui est attribué.

Il n'y a pas vraiment une chose comme un objet NULL instance , vous ne pouvez donc pas créer de référence C ++ à une telle chose. Dans d'autres langues, une référence nulle est l'équivalent d'un pointeur C ++ NULL; Cela ne contient rien.

Maintenant, en ce qui concerne vos autres réflexions: 1. Avoir des références non nullables est un bonne chose à mon esprit; Cela signifie que vous obtenez tous les avantages de passer par référence sans aucune des exigences de vérifier les NULLS partout sur la place. 2. Les références nullables ne remplacent pas les pointeurs ... Si vous avez besoin de faire de la mémoire ou de l'IO, vous souhaitez que vous souhaitiez un accès brut à la mémoire et à des appareils mappés en mémoire. Vous pouvez consulter C # (ou C ++ / CLR), qui a géré des références et des pointeurs non gérés pour cette raison précisément.


0 commentaires