web-dev-qa-db-fra.com

error: initialisation non valide de la référence non-const de type 'int &' à partir d'une valeur rvalue de type 'int'

Mauvaise forme:

int &z = 12;

Forme correcte:

int y;
int &r = y;

Question:
Pourquoi le premier code est-il faux? Quel est le "signification" de l'erreur dans le titre?

77
Aquarius_Girl

C++ 03 3.10/1 dit: "Chaque expression est une valeur ou une valeur." Il est important de se rappeler que l'évaluation par rapport à l'évaluation est une propriété des expressions, pas des objets.

Lvalues ​​nomme les objets qui persistent au-delà d'une seule expression. Par exemple, obj, *ptr, ptr[index] Et ++x Sont tous des valeurs.

Les valeurs sont des valeurs temporaires qui s'évaporent à la fin de la pleine expression dans laquelle elles vivent ("au point virgule"). Par exemple, 1729, x + y, std::string("meow") et x++ Sont tous des valeurs rvalues.

L'adresse de l'opérateur exige que son "opérande soit une valeur". si nous pouvions prendre l'adresse d'une expression, l'expression est une valeur, sinon c'est une valeur.

 &obj; //  valid
 &12;  //invalid
119
BruceAdi
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 pareil 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 être créé en premier. Comme l'objet n'a pas de nom, il s'agit d'un objet temporaire. Il n'a pas de nom. De cette explication, il est devenu assez clair pourquoi le deuxième cas est bien.

Un objet temporaire peut être lié à la référence const, ce qui signifie que vous pouvez faire ceci:

const int &z = 12; //ok

Référence C++ 11 et Rvalue:

Par souci d'exhaustivité, j'aimerais 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 const n’est plus nécessaire, même si l’objet auquel z se lie est un objet temporaire créé à partir de 12.

Depuis que C++ 11 a introduit rvalue-reference, int& s'appelle désormais lvalue-reference.

46
Nawaz

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 vous pouvez faites est

const int& z = 12;

Les liaisons de référence non-const et const suivent des règles différentes

Voici les règles du langage C++:

  • une expression composée d'un nombre littéral (12) est une "valeur"
  • il n'est pas autorisé de créer une référence non-const avec une valeur rvalue: int &ri = 12; est mal formé
  • il est permis de créer une référence const avec une valeur rvalue: dans ce cas, un objet non nommé est créé par le compilateur; cet objet persistera tant que la référence elle-même existe.

Vous 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 valeur rvalue. Il n'y a rien d'incohérent ou 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 eu raison d’éviter ce risque.

4
curiousguy

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".

MODIFIER::

Je pense à

int &x = y;

presque équivalent à

int* __px = &y;
#define x (*__px)

__px est un nouveau nom, et le #define x fonctionne uniquement à l'intérieur du bloc contenant la déclaration de x référence.

0