Pourquoi sont des références pas reseatable en C++
C++ références ont deux propriétés:
- Ils pointent toujours vers le même objet.
- Ils ne peuvent pas être 0.
Pointeurs sont à l'opposé:
- Ils peuvent pointer vers des objets différents.
- Ils peuvent être 0.
Pourquoi n'est-il pas "non nullable, reseatable de référence ou pointeur" en C++? Je ne peux pas penser à une bonne raison pourquoi les références ne devrait pas être reseatable.
Edit:
La question revient souvent parce que j'ai l'habitude d'utiliser des références quand je veux faire en sorte qu'une "association" (j'évite les mots "de référence" ou "pointeur" ici) n'est jamais nulle.
Je ne pense pas que j'ai jamais pensé "grand que cet réf fait toujours référence au même objet". Si les références ont été reseatable, on pourrait toujours obtenir le comportement actuel comme ceci:
int i = 3;
int& const j = i;
C'est déjà légal C++, mais vide de sens.
Je rappelle ma question comme ceci: "Quel est le raisonnement derrière la" référence est l'objet " design? Pourquoi était-il utile d'avoir des références toujours être le même objet, au lieu de seulement lorsque déclarée const?"
Acclamations, Felix
- Je sais c'est un peu tard, mais c'Michael Burr réponse semble être la plus complète. Il explique de Stroustrup philosophique des décisions de conception. Tout le monde semble être à la mendicité, l'argument (dans un rond-point moyen).
Vous devez vous connecter pour publier un commentaire.
La raison que le C++ ne permet pas de relier des références est donnée dans de Stroustrup "la Conception et l'Évolution de C++" :
En C++, il est souvent dit que "la référence est l'objet". En un sens, c'est vrai: si les références sont traités comme des pointeurs lorsque le code source est compilé, la référence est destiné à signifier un objet qui n'est pas copié quand une fonction est appelée. Car les références ne sont pas directement adressable (par exemple, les références n'ont pas d'adresse, & retourne l'adresse de l'objet), il ne serait pas sémantiquement sens pour les réaffecter. En outre, le C++ a déjà des pointeurs, qui gère la sémantique de re-paramétrer.
Car alors vous auriez pas reseatable type qui ne peut pas être 0. À moins que, vous avez inclus 3 types de références/pointeurs. Ce qui pourrait compliquer la langue pour très peu de gain (Et puis pourquoi ne pas ajouter la 4ème trop? Non reseatable de référence qui peut être égal à 0?)
Une meilleure question peut être, pourquoi voulez-vous des références à être reseatable? Si elles l'étaient, qui les rendrait moins utile dans beaucoup de situations. Il serait plus difficile pour le compilateur fasse analyse d'alias.
Il semble que la raison principale des références en Java ou C# sont reseatable est parce qu'ils font le travail de pointeurs. Ils désignent des objets. Ils ne sont pas des alias pour un objet.
Ce qui devrait l'effet de la suite être?
En C++ aujourd'hui, avec les non-reseatable des références, c'est simple. j est un alias pour moi, et je termine avec la valeur 43.
Si les références ont été reseatable, puis troisième ligne à lier la référence j d'une valeur différente. Il n'aurait plus alias je, mais plutôt l'entier littéral 43 (ce qui n'est pas valide, bien sûr). Ou peut-être plus simple (ou au moins syntaxiquement valide) exemple:
Avec reseatable références. j aurait point de k après l'évaluation de ce code.
Avec C++de non-reseatable références, j toujours des points de i, et i est affectée de la valeur 43.
En faisant des références reseatable la sémantique de la langue. La référence ne peut plus être un alias pour une autre variable. Au lieu de cela, il devient un type distinct de la valeur, avec son propre opérateur d'affectation. Et puis, l'une des utilisations les plus courantes de références serait impossible. Et n'avait rien à gagner en échange. La nouvellement acquise, la fonctionnalité pour les références existait déjà sous la forme de pointeurs. Alors maintenant, nous aurions deux façons de faire la même chose, et aucun moyen de faire ce que les références dans le courant de langage C++ ne.
int* const
. Pour des raisons de cohérence, il devrait être de 4, comme peut-être nulle, et reseatable sont assez orthogonale.Une référence n'est pas un pointeur, il peut être mis en œuvre comme un pointeur dans le fond, mais son concept de base n'est pas équivalent à un pointeur. Une référence doit être regardé comme il
*is*
l'objet auquel il fait référence. Par conséquent, vous ne pouvez pas la changer, et il ne peut pas être NULL.Un pointeur est simplement une variable qui contient une adresse mémoire. Le pointeur lui-même a une adresse en mémoire de sa propre, et à l'intérieur de l'adresse mémoire il détient une autre adresse mémoire qu'il est dit à point de. Une référence n'est pas la même, il n'a pas une adresse de sa propre, et ne peut donc pas être changé pour "tenir" une autre adresse.
Je pense que le parashift C++ FAQ sur les références l'exprime le mieux:
et de nouveau en FAQ 8.5 :
Un reseatable de référence serait fonctionnellement identique à un pointeur.
Concernant la possibilité de valeur null: vous ne pouvez pas garantir qu'un tel "reseatable de référence" est non NULLE au moment de la compilation, un tel examen aurait lieu au moment de l'exécution. Vous pourriez réaliser vous-même par l'écriture d'un pointeur intelligent de style de modèle de classe qui lève une exception lors de l'initialisation ou affectés NULL:
Ce qui peut être utile à l'occasion, -- une fonction prenant un
non_null_pointer<int>
paramètre certainement communique plus d'informations à l'appelant qu'une fonction prenantint*
.Il aurait été probablement moins source de confusion pour le nom de C++ références des "alias"? Comme d'autres l'ont mentionné, les références en C++ doit être bien que la variable ils se réfèrent, non pas comme un pointeur/référence à la variable. En tant que tel, je ne peux pas penser à une bonne raison, ils doit être programmable.
lorsque vous traitez avec des pointeurs, il est souvent judicieux permettant la valeur null (et sinon, vous voulez probablement une référence à la place). Si vous souhaitez interdire la tenue null, vous pouvez toujours votre propre code de type pointeur intelligent 😉
Intrestingly, beaucoup de réponses ici sont un peu floue ou même à côté de la question (par exemple, ce n'est pas parce que les références ne peuvent pas être zéro ou similaire, en fait, vous pouvez facilement construire un exemple de cas où la référence est égale à zéro).
La vraie raison pour laquelle la re-définition d'une référence n'est pas possible, est plutôt simple.
Pointeurs de vous permettre de faire deux choses: Pour modifier la valeur derrière le pointeur (soit par le biais de la
->
ou la*
opérateur), et de modifier le pointeur lui-même (direct attribuer=
). Exemple:*p = 42;
p = 0;
Références vous permettent de modifier la valeur. Pourquoi? Depuis il n'y a pas d'autre syntaxe pour exprimer la re-régler. Exemple:
En d'autres termes, il serait ambiguë si vous avez été autorisé à re-définir une référence. Il fait encore plus de sens lorsque le passage par référence:
Espère que ça aide 🙂
C++ références peuvent parfois être forcé à être 0 avec certains compilateurs (c'est juste une mauvaise idée de le faire*, et il viole la norme*).
EDIT: selon différentes personnes qui connaissent le standard beaucoup mieux que moi-même, le code ci-dessus donne "un comportement non défini". Dans au moins certaines versions de GCC et de Visual Studio, je l'ai vu faire que l'on attend: l'équivalent de définition d'un pointeur à NULL (et provoque une exception de pointeur NULL en cas d'accès).
Vous ne pouvez pas faire ceci:
...pour la même raison pourquoi secondInt et firstInt n'ont pas la même valeur ici:
Ce n'est pas vraiment une réponse, mais une solution pour contourner cette limitation.
Fondamentalement, lorsque vous essayez de "relier" d'une référence, vous êtes en train d'essayer d'utiliser le même nom pour désigner une nouvelle valeur dans le contexte suivant. En C++, ceci peut être résolu par l'introduction d'un bloc de portée.
Dans jalf.com l'exemple de
si vous voulez changer j', écrire comme ci-dessus. Cependant, si vous souhaitez modifier le sens de
j
à direk
, vous pouvez le faire:J'imagine que c'est lié à l'optimisation.
Statique d'optimisation est beaucoup plus facile quand vous pouvez connaître sans ambiguïté que peu de mémoire d'une variable de moyens. Les pointeurs de briser cette condition et re-paramètrables de référence serait de trop.
Parce que parfois, les choses ne devraient pas être re-pointable. (E. g., la référence à un Singleton.)
Parce que c'est grand en fonction de savoir que votre argument ne peut pas être null.
Mais surtout, parce qu'il permet d'utiliser quelque chose qui est vraiment un pointeur, mais qui agit comme une valeur locale de l'objet. C++ essaie dur, pour citer Stroustrup, pour faire des instances de classe comme de "ints d". Passage d'un int par vaue est pas cher, car un int fitss dans une machine à enregistrer. Les Classes sont souvent plus importantes que les ints, et leur passage par valeur a une surcharge importante.
Être en mesure de passer un pointeur (qui est souvent la taille d'un int, ou peut-être deux ints) qui "ressemble" à un objet de valeur nous permet d'écrire plus propre code, sans le "détail de l'implémentation" de déréférence. Et, avec la surcharge d'opérateur, il permet d'écrire des classes de l'utilisation d'une syntaxe similaire à la syntaxe utilisée avec ints. En particulier, il permet d'écrire des classes template avec la syntaxe qui peut également être appliqué à la primitive, comme les entiers, et les classes (comme un nombre Complexe de la classe).
Et, avec la surcharge d'opérateur en particulier, il y a des endroits ont été on devrait retourner un objet, mais encore une fois, c'est beaucoup moins cher pour renvoyer un pointeur. Oncve encore une fois, de retour d'une référence est notre "out.
Et les pointeurs sont durs. Pas pour vous, peut-être, et pas à n'importe qui qui réalise un pointeur est la valeur d'une adresse de mémoire. Mais rappelant mon CS 101 classe, ils ont déclenché un certain nombre d'étudiants.
peut être source de confusion.
Diable, après 40 ans de C, les gens ne peuvent même pas d'accord si une déclaration de pointeur doit être:
ou
char *p
dit que*p
est unchar
. Je suis venu à partir d'un Pascal, de l'endroit oùvar p: ^Char
serait la syntaxe, mais je trouve toujours bizarre quand je vois Pascal stylechar*
pointeur de la syntaxe en C/C++... Surtout lorsque plusieurs variables sont définies à la fois par exemplechar* x, y, z
Je me suis toujours demandé pourquoi ils ne font pas une référence opérateur d'affectation (disons :=) pour ce.
Juste pour obtenir sur quelqu'un de nerfs, j'ai écrit un peu de code pour changer la cible d'une référence dans une structure.
Non, je ne recommande pas de répéter mon truc. Il va se casser si porté suffisamment d'architecture différents.
Être à moitié sérieux: à mon humble avis afin de les rendre peu plus différent de pointeurs 😉 vous savez que Vous pouvez écrire:
Si vous pouviez aussi plus tard écrire:
serait-il judicieux d'avoir toutes les références côtés avec des pointeurs?
Le fait que les références en C++ ne sont pas les valeurs null est un effet secondaire d'entre eux étant qu'un alias.
Je suis d'accord avec la accepté de répondre.
Mais pour constness, ils se comportent un peu comme des pointeurs si.
œuvres.
Voir
Raisons de conception pour le comportement de référence des membres de classes passé par référence const
Il y a une solution de contournement si vous voulez une variable de membre qui est une référence et vous voulez être en mesure de relier à elle. Bien que je trouve qu'il est utile et fiable, note qu'il utilise (très faible) hypothèses sur la disposition de la mémoire. C'est à vous de décider si c'est à l'intérieur de vos normes de codage.
Ce n'est pas très efficace que vous avez besoin d'un type distinct pour chaque reassignable champ de référence et de leur faire des classes de base; de plus, il y a une faiblesse de l'hypothèse ici qu'une classe a un seul type de référence n'ont pas une
__vfptr
ou de tout autretype_id
domaine qui pourrait détruire exécution des liaisons de MyType. Tous les compilateurs je sais satisfaire à cette condition (et il serait insensé de ne pas le faire).