Mauvaise forme:
int &z = 12;
Forme correcte:
int y;
int &r = y;
Question :
Pourquoi le premier code est-il erroné? Quelle est la « signification » de l'erreur dans le titre?
Mauvaise forme:
int &z = 12;
Forme correcte:
int y;
int &r = y;
Question :
Pourquoi le premier code est-il erroné? Quelle est la « signification » de l'erreur dans le titre?
(ostringstream() << "x=" << x).str()
Réponses:
C ++ 03 3.10 / 1 dit: "Chaque expression est une lvalue ou une rvalue." Il est important de se rappeler que la valeur par rapport à la valeur est une propriété des expressions et non des objets.
Lvalues nomme les objets qui persistent au-delà d'une seule expression. Par exemple, obj
, *ptr
, ptr[index]
et ++x
sont tous lvalues.
Les valeurs R sont des valeurs temporaires qui s'évaporent à la fin de l'expression complète dans laquelle elles vivent ("au point-virgule"). Par exemple, 1729
, x + y
, std::string("meow")
et x++
sont tous rvalues.
L'opérateur d'adresse de demande que son "opérande doit être une valeur l". si nous pouvons prendre l'adresse d'une expression, l'expression est une lvalue, sinon c'est une rvalue.
&obj; // valid
&12; //invalid
int & = 12;
est invalide, le standard dit qu'un littéral de chaîne est une lvalue, les autres littéraux sont des rvalues.
std::string("meow")
construit un objet de type std::string
et renvoie une rvalue qui désigne cet objet, 1729
n'a pas d'effet secondaire et donne une valeur 1729 comme rvaleur de type int
.
"Lvalues name objects that persist beyond a single expression."
est une déclaration 100% correcte. Au contraire, votre exemple (const int &)1
est incorrect, car ce n'est PAS un objet "nommé".
int &z = 12;
Sur le côté droit, un objet temporaire de type int
est créé à partir du littéral intégral 12
, mais le temporaire ne peut pas être lié à une référence non const. D'où l'erreur. C'est la même chose que:
int &z = int(12); //still same error
Pourquoi un temporaire est créé? Parce qu'une référence doit faire référence à un objet dans la mémoire, et pour qu'un objet existe, il doit d'abord être créé. Puisque l'objet n'est pas nommé, il s'agit d'un objet temporaire . Il n'a pas de nom. À partir de cette explication, il est devenu assez clair pourquoi le deuxième cas est bon.
Un objet temporaire peut être lié à une référence const, ce qui signifie que vous pouvez le faire:
const int &z = 12; //ok
Par souci d'exhaustivité, je voudrais ajouter que C ++ 11 a introduit rvalue-reference, qui peut se lier à un objet temporaire. Donc, en C ++ 11, vous pouvez écrire ceci:
int && z = 12; //C+11 only
Notez qu'il y a au &&
lieu de &
. Notez également que ce const
n'est plus nécessaire, même si l'objet auquel z
se lie est un objet temporaire créé à partir d'intégrale-littérale 12
.
Depuis que C ++ 11 a introduit rvalue-reference , il int&
est désormais appelé lvalue-reference .
12
est une constante de compilation qui ne peut pas être modifiée contrairement aux données référencées par int&
. Ce que tu peux faire c'est
const int& z = 12;
void f( vector<int> const & )
, qui est idiomatique pour passer un vecteur qui ne doit pas être modifié. Le problème maintenant est que ce f( vector<int>(5) )
serait incorrect et que l'utilisateur devrait fournir une surcharge différente, void f( vector<int> v ) { f(v); }
ce qui est trivial.
f( vector<int>(5) )
, le compilateur crée un temporaire, puis lie la référence à ce temporaire, et de même s'il y avait une conversion implicite de 5
directement. Cela permet au compilateur de générer une signature unique pour la fonction et permet une implémentation de la fonction par un seul utilisateur. À partir de là, un comportement similaire est défini pour le reste des utilisations de références constantes pour la cohérence.
T const & r = *ptr;
, toute utilisation ultérieure de r
dans la fonction peut être remplacée par *ptr
, et r
n'a pas besoin d'exister au moment de l'exécution) ou il peut devoir être implémenté en conservant l'adresse de l'objet qu'il alias (envisagez de stocker une référence en tant que membre d'un objet) - qui est implémenté comme un pointeur auto-référencé.
Voici les règles du langage C ++:
12
) est une "rvalue"int &ri = 12;
est mal forméeVous devez comprendre que ce sont des règles C ++. Ils sont juste.
Il est facile d'inventer un langage différent, disons C ++, avec des règles légèrement différentes. En C ++ ', il serait permis de créer une référence non-const avec une rvalue. Il n'y a rien d'incohérent ni d'impossible ici.
Mais cela permettrait un code risqué où le programmeur pourrait ne pas obtenir ce qu'il voulait, et les concepteurs C ++ ont à juste titre décidé d'éviter ce risque.
Les références sont des "pointeurs cachés" (non nuls) vers des choses qui peuvent changer (lvalues). Vous ne pouvez pas les définir comme une constante. Ce devrait être une chose "variable".
ÉDITER::
Je pense à
int &x = y;
comme presque équivalent de
int* __px = &y;
#define x (*__px)
où __px
est un nouveau nom, et les #define x
œuvres uniquement à l'intérieur du bloc contenant la déclaration de x
référence.
const
:)
const