C'est un caprice/fonction en C++. Bien que nous ne pensons pas de références que de types, en fait, elles "s'asseoir" dans le système de type. Bien que cela semble maladroit (étant donné que lorsque les références sont utilisées, la référence sémantique se produit automatiquement et la référence "sort de la voie"), il y a quelques défendable raisons pour lesquelles les références sont modélisés dans le système de type plutôt que comme un attribut distinct à l'extérieur de type.
Tout d'abord, permettez-nous de considérer que chaque attribut d'une déclaration de nom doit être dans le type de système. À partir du langage C, nous ont "avec la classe de stockage", et "lien". Un nom peut être présenté en tant que extern const int ri
, où l' extern
indique statique de la classe de stockage et de la présence de la liaison. Le type est juste const int
.
C++ évidemment embrasse la notion que les expressions ont des attributs qui sont en dehors du système de type. La langue a maintenant un concept de "classe", qui est une tentative d'organiser le nombre croissant de non-type des attributs qu'une expression peut les exposer.
Pourtant, les références sont des types. Pourquoi?
Il sert à être expliqué en C++ tutoriels qu'une déclaration telle que celle - const int &ri
introduite ri
de type const int
, mais la référence à la sémantique. Qui font référence à la sémantique n'était pas un type, c'était tout simplement une sorte d'attribut indiquant une relation inhabituelle entre le nom et l'emplacement de stockage. En outre, le fait que les références ne sont pas les types a été utilisé pour expliquer pourquoi vous ne pouvez pas construire des types de références, même si le type de construction de la syntaxe permet. Par exemple, des tableaux ou des pointeurs vers des références n'étant pas possible: const int &ari[5]
et const int &*pri
.
Mais en fait, les références sont les types de decltype(ri)
récupère une référence de type de nœud qui est sans réserve. Vous devez descendre passé ce nœud dans le type de l'arbre pour obtenir le type sous-jacent avec remove_reference
.
Lorsque vous utilisez ri
, la référence est résolu de manière transparente, de sorte qu' ri
"ressemble i
" et peut être appelé un "alias" pour elle. Dans le système de type, même si, ri
a, en fait, un type qui est "laréférence à l' const int
".
Pourquoi sont des références types?
Considérer que, si les références étaient pas les types, ces fonctions seraient considérées comme ayant le même type:
void foo(int);
void foo(int &);
Qui simplement ne peut pas être pour des raisons qui sont à peu près de soi. S'ils avaient le même type, cela signifie que la déclaration serait approprié pour la définition, et donc chaque (int)
fonction devrait être soupçonnées de prendre une référence.
De même, si les références n'étaient pas des types, alors ces deux déclarations de classe serait l'équivalent:
class foo {
int m;
};
class foo {
int &m;
};
Il serait correct pour une unité de traduction à utiliser une déclaration, et une autre unité de traduction dans le même programme de déclaration.
Le fait est qu' une référence implique une différence dans la mise en œuvre et il est impossible de séparer ce de type, parce que le type en C++ a à voir avec la mise en œuvre d'une entité: sa "mise en page" en bits pour ainsi dire. Si les deux fonctions ont le même type, elles peuvent être invoquées avec le même binaire conventions d'appel: l'ABI est le même. Si deux structures ou classes ont le même type, leur mise en page est la même, ainsi que la sémantique de l'accès à tous les membres. La présence de références à des changements de ces aspects de types, et c'est donc une conception simple décision de les intégrer dans le système de type. (Notez toutefois un contre-argument ici: struct/membre de la classe peuvent être static
, ce qui modifie également la représentation; or, ce n'est pas le type!)
Ainsi, les références sont dans le système de type "citoyens de seconde classe" (pas à la différence des fonctions et des tableaux en C ISO). Il y a certaines choses que nous ne pouvons pas "faire" avec des références telles que de déclarer des pointeurs vers des références, ou des tableaux. Mais cela ne veut pas dire qu'ils ne sont pas les types. Ils ne sont pas seulement des types d'une manière qui fait sens.
Pas tous ces de deuxième classe,-les restrictions sont essentiels. Étant donné qu'il existe des structures de références, il pourrait y avoir des tableaux de références! E. g.
// fantasy syntax
int x = 0, y = 0;
int &ar[2] = { x, y };
// ar[0] is now an alias for x: could be useful!
Ce n'est pas implémentée en C++, c'est tout. Des pointeurs vers les références n'ont pas de sens, bien que, parce qu'un pointeur levé à partir d'une référence va juste à l'objet référencé. Probablement la raison pour laquelle il n'existe pas de tableaux de références, c'est que le C++ les gens considèrent les tableaux à une sorte de bas niveau de fonctionnalité héritée de C qui est cassé dans de nombreuses façons qui sont irréparables, et ils ne veulent pas toucher les tableaux en tant que base pour quelque chose de nouveau. L'existence de tableaux de références, cependant, serait de faire un exemple clair de la façon dont les références doivent être de types différents.
Non-const
-qualifiable types: trouvé dans la norme ISO C90, trop!
Certaines réponses sont allusion au fait que les références ne pas prendre un const
de qualification. C'est plutôt un hareng rouge, parce que la déclaration const int &ri = i
n'est même pas tenter de faire un const
-qualifiés de référence: c'est une référence à un const qualifiés de type (qui lui, n'est pas const
). Tout comme const in *ri
déclare un pointeur vers quelque chose d' const
, mais que le pointeur n'est pas const
.
Cela dit, il est vrai que les références ne peuvent pas prendre en const
qualifier eux-mêmes.
Pourtant, ce n'est pas si bizarre. Même dans la norme ISO C 90 langue, pas tous les types peuvent être const
. À savoir, les tableaux ne peuvent pas être.
Tout d'abord, la syntaxe n'existe pas de déclaration d'une const tableau: int a const [42]
est erronée.
Cependant, ce que la déclaration ci-dessus est d'essayer de faire peut être exprimé par le biais d'un intermédiaire, typedef
:
typedef int array_t[42];
const array_t a;
Mais ce n'est pas faire ce à quoi il ressemble, il ne. Dans cette déclaration, il n'est pas a
qui reçoit const
qualifiés, mais les éléments! C'est-à-dire, a[0]
est const int
, mais a
est juste "tableau de int". Par conséquent, cela ne nécessite pas un diagnostic:
int *p = a; /* surprise! */
Ce n':
a[0] = 1;
Encore une fois, ce qui souligne l'idée que les références sont en quelque sorte de "seconde classe" dans le système de type, comme des tableaux.
Notez comment l'analogie est encore plus profondément, comme les tableaux ont également un "invisible comportement de conversion", comme des références. Sans le programmeur d'avoir à utiliser de manière explicite de l'opérateur, l'identificateur a
se transforme automatiquement en une int *
pointeur, comme si l'expression &a[0]
a été utilisé. Ceci est analogue à la façon dont une référence ri
, lorsque nous l'utilisons comme une expression primaire, comme par magie, désigne l'objet i
auquel il est lié. C'est juste un autre "décroissance" comme le "tableau de pointeur de la décroissance".
Et tout comme nous ne devons pas devenir confus par le "tableau de pointeur de la" désintégration de penser à tort que "les tableaux sont juste des pointeurs en C et C++", de même, nous ne devons pas penser que les références sont des alias qui n'ont pas de type de leur propre.
Lors de l' decltype(ri)
supprime l'habitude de conversion de la référence à son référent de l'objet, ce n'est pas si différent de sizeof a
suppression de la pile-à-pointeur de conversion et d'exploitation sur le type de tableau lui-même pour calculer sa taille.