donné:
int main() { int x = 0; int y = x; // <--- }
5 Réponses :
Est-ce ce que vous recherchez: P>
§3.10 / 7 p>
Chaque fois qu'un lvalue apparaît dans un contexte où une r devale est attendue, la lvalue est convertie en une r devalue; Voir 4.1, 4.2 et 4.3. P> blockQuote>
et je pense que lorsque vous écrivez
int y = x code>, il copie essentiellement la em> la valeur em> contenu dans l'objet
x code> qui est un lvalue, Mais la valeur em> est une r devalue, d'où le contexte attend un rvalue. p>
§4.1 / 2 dit, P>
La valeur contenue dans l'objet indiqué par la LValue est le résultat de la rapession. P> blockQuote>
Peut-être que ces deux citations clarifient votre doute. Corrigez-moi si ma compréhension est fausse. Je voudrais apprendre nouveaux em> choses. P>
Commentaire de Tomalak: P>
Mon problème avec c'est que INT & Y = X; est valable, donc dans ce cas de cours x peut ne pas être une rvalue. Je ne sais pas à quel point la différence dans mon exemple fait ne pas perfectionner cela, bien que p> blockQuote>
Eh bien
int & y = x code> ne copie pas la valeur. Cela crée juste un alias de l'objet lui-même. Mais comme j'ai précédemment dit
int y = x code>, fondamentalement copies strong> la valeur em> qui est une r devalue. Par conséquent, le contexte attend un rvalue, comme une copie est en cours. P>
Presque, mais où est-ce qu'une r devalue?
Mon problème avec c'est que int & y = x; code> est valide, donc dans ce cas de cours
x code> peut ne pas être un rvalue i>. Je ne sais pas à quel point la différence dans mon exemple en fait une certaine pertinence.
@Tomalak Geret'kal: J'ai déjà répondu à cette question ci-dessus, l'affectation entière (affectation pour toute classe définie par l'utilisateur) prend l'argument latéral droit en tant que rvalue. Sinon, int x = 5; code> ne serait pas valide, car
5 code> est une r devalue et une rvalue ne peut pas être convertie en une lvalue.
@Downvoter: Je ne comprends pas la raison du bowvote. Pourriez-vous me le signaler?
@Tomalak Geret'kal: Si le commentaire "Affectation! = Initialisation" fait référence à mon commentaire ci-dessus, vous avez raison de ne pas être identiques et que j'ai mal utilisé le terme, et pourtant, le commentaire se tient. Substituez «Affectation» pour «initialisation» dans le commentaire et vous êtes défini.
@David: Excellent. Mon vérification valait la peine. :)
Je trouve plus facile (s'il est peut-être pas 100% précis) de penser à Lvalue-S en tant que vrais objets et de rvalue-S comme valeur stockée dans l'objet. L'expression sur la clause spécifique de la norme qui dicte Cette conversion ... Eh bien, le plus proche que je puisse penser, c'est 4.1 [CONV.LVALUE] / 2 (LVALUE À LA CONVERSION DE RVALUE): P> La valeur contenue dans l'objet indiqué par la LValue est le résultat de la rapession. P>
blockQuote> L'exigence que le côté droit de la mission est une r devalue est implicite ou manquant à partir de 5.17 [expr.ass], mais c'est le cas ou l'expression suivante serait une erreur depuis le RHS est une rvalue et il n'y a pas de conversion de rvalue à lvalue: p> EDIT: Pour l'initialisation, 8,5 [DCL.Init] / 14, dernière balle (qui fait référence à fondamentale types) états (mines): emphasis p> Ce valeur em> il signifie que l'expression lvalue dans votre exemple est lire em> (par exemple converti en un rvalue). En tout cas l'alinéa précédent qui faisait référence à la cession pourrait être appliquée ici: si l'initialisation a nécessité une lvalue em> au lieu d'un rvalue em>, l'expression x code> est une expression de lvalue qui fait référence à l'objet
x code> défini dans la première ligne, mais lorsqu'il est utilisé comme côté droit d'une affectation à un type qui n'est pas Un type défini par l'utilisateur La valeur em> est lue, et c'est là que la conversion de Lvalue vers RValue est effectuée: lisant le contenu de l'objet.
int i = 0; < / code> serait mal formé. p> p>
Joli. Je pense que c'est une déduction assez solide. :)
"L'exigence que le côté droit de la mission est une rvalue est implicite ou manquant à partir de 5,17 [expr.ass], mais c'est le cas ou l'expression suivante serait une erreur puisque le RHS est une r devalue et il y a Aucune conversion de rvalue à lvalue "<- cela ne suit pas entièrement, logiquement. "RHS doit être une rvalue, ou le RHS doit être un lvalue (et ce dernier ne peut pas être vrai, donc le premier doit être)" est ce que vous dites; On dirait une fausse dichotomie pour moi?
@Tomalak: Non, le raisonnement est que le côté droit de l'expression est nécessaire pour être soit b> un lvalue ou une rapalité, mais pas les deux. Maintenant: si le côté droit de l'expression devait être une expression de lvalue, alors i = 5 code> échouerait; Cette expression est valide (n'a pas échoué), Ergo Le côté droit de l'expression ne peut pas être nécessaire pour être un lvalue i>. Étant donné que la seule autre option est une rvalue i> (au moins en C ++ 03), l'expression
x = y code> prend une lvalue comme LHS (ceci est explicite dans la norme ) et une rvalue comme RHS (je n'ai pas pu trouver de citation précise pour cela)
Pourquoi ne peut-il pas être soit B> selon le contexte?
3.10 LVALUES ET RVALUES P>
1 Chaque expression est soit une lvalue ou une rvalue. P>
2 Un lvalue fait référence à un objet ou fonction. Une certaine rvalue expressions - celles de la classe ou Type de classe CVQualifiée - Reportez-vous également à Objets.47) P>
3 [Note: Quelques opérateurs intégrés et Les appels de fonction donnent des lvalues. [Exemple: si e est une expression de Type de pointeur, alors * e est un lvalue expression faisant référence à l'objet ou fonction à laquelle e points. Comme un autre exemple, la fonction Int & F (); rendements un lvalue, donc l'appel f () est un expression de lvalue. ] p>
- [Note: Certains opérateurs Builin s'attendent à des opérandes de Lvalue. [Exemple: intégré Les opérateurs d'affectation s'attendent tous à leur les opérandes de gauche doivent être des lvalues. ] Les autres opérateurs intégrés produisent des r devalues, Et certains attendent-les. [Exemple: le Les opérateurs unis et binaires + attendent Avalue Arguments et rendement RValue résultats. ] La discussion de chaque L'opérateur intégré à l'article 5 indique si cela s'attend à ce que les opérandes de lvalue et que ce soit de la nièce de lvalue. ] li> ol>
5 le résultat de l'appel d'une fonction cela ne renvoie pas une référence est un rvalue. Les opérateurs définis par l'utilisateur sont fonctions, et si ces opérateurs attendre ou donner des lvalues de rendement est déterminé par leurs types de paramètres et de retour. p>
6 une expression qui détient un Objet temporaire résultant d'une distribution à un type de non-référence est une r devalue (Cela inclut la création explicite d'un objet utilisant la notation fonctionnelle (5.2.3)). P>
7 Chaque fois qu'un lvalue apparaît dans un contexte où une r devale est attendue, Le lvalue est converti en une r devalue; Voir 4.1, 4.2 et 4.3. Strong> P> 8 la discussion de référence initialisation en 8.5.3 et de Les temporaires en 12.2 indiquent la comportement des lvalues et des rapaces dans autres contextes importants. P>
9 rvalues de classe peut avoir CVqualifiée les types; Les ruvales non classes ont toujours types cvunqualifié. Les rabais doivent toujours avoir des types complets ou le vide taper; En plus de ces types, Les lvalues peuvent également avoir incomplet Types. P>
10 un lvalue pour un objet est nécessaire pour modifier le objet sauf qu'un rvalue de classe type peut également être utilisé pour modifier son référent dans certaines circonstances. [Exemple: une fonction de membre appelée Un objet (9.3) peut modifier l'objet. ] p>
11 Les fonctions ne peuvent pas être modifiées, mais Les pointeurs vers des fonctions peuvent être modifiable. P>
12 un pointeur à un type incomplet peut être modifiable. À un moment de la programme lorsque le point indiqué à tapez est complet, l'objet auquel le Les points de pointeur peuvent également être modifiés. P>
13 Le référent d'un Consqualifié L'expression ne doit pas être modifiée (à travers cette expression), sauf que Si c'est du type de classe et a un composant mutable, ce composant peut être modifié (7.1.5.1). P>
14 Si une expression peut être utilisée pour modifier l'objet auquel il fait référence, L'expression est appelée modifiable. UNE programme qui tente de modifier un objet à travers une lvalue non chargée ou expression de rvalue est malformée. p>
15 Si un programme tente d'accéder à la valeur stockée d'un objet à travers un lvalue d'autre que l'un des Types suivants Le comportement est indéfinle48): - le type dynamique de l'objet, - une version CVQualifiée de le type dynamique de l'objet, - a Tapez qui est le signé ou non signé Tapez correspondant au type dynamique de l'objet, - un type qui est le type signé ou non signé correspondant à une version cvalifiée de la type dynamique de l'objet, - un Type d'agrégat ou d'union qui comprend un des types susmentionnés parmi ses membres (y compris, récursivement, un membre d'un sous-assemblée ou contenu Union), - un type qui est (éventuellement cvqualified) Type de classe de base de la type dynamique de l'objet, - un char ou type de caractère non signé. P> blockQuote>
i les em> croyez que cela est intuitif dans une certaine mesure (ce que les autres ont déjà dit - la valeur est nécessaire, donc il est donc nécessaire de convertir le concepteur d'objet en la valeur qui y est contenue). Le meilleur que je pouvais trouver, à 4p3: p>
Une expression e peut être implicitement convertie en un type T si et uniquement si la déclaration "t t = e;" est bien formé, pour une variable temporaire inventée T (8,5). L'effet de la conversion implicite est la même chose que l'exécution de la déclaration et de l'initialisation, puis en utilisant la variable temporaire à la suite de la conversion. Le résultat est un lvalue si T est un type de référence (8.3.2) et une r devalue autrement. L'expression e est utilisée comme une lvalue si et uniquement si l'initialisation l'utilise comme une lvalue. Em> p>
blockQuote>
Notez le "Si et seulement si" à la fin - L'initialisateur est utilisé comme une rvalue em>, car l'initialisation l'utilise comme une rvalue (résultat de la conversion). Donc, à 3.10P7 P>
Chaque fois qu'un lvalue apparaît dans un contexte où une r devale est attendue, la lvalue est convertie en une r devalue; Voir 4.1, 4.2 et 4.3. P>
blockQuote>
Edit: Le paragraphe de saisie de 4P3 peut être trouvé au 8.5p16, dernière balle: p>
Sinon, la valeur initiale de l'objet étant initialisée est la valeur (éventuellement convertie) de l'expression d'initialisation. p>
blockQuote>
Notez également les commentaires ci-dessous. P>
Mais y a-t-il une conversion du tout? Vous commencez par un int code> et vous vous retrouvez avec un
int code>. Par ce raisonnement seul, je ne suis pas sûr que la première citation s'applique.
@Tomalak Une conversion ne commence pas vraiment avec un type, mais avec une expression i>. Et l'expression est convertie d'un LValue Int à une rvalue d'int.
@LitB: C'est la logique circulaire. "Il y a une conversion, à cause de cette règle parlant de ce qui se passe lorsqu'une conversion est requise."
@Tomalak Je suis d'accord qu'un raisonnement aussi circulaire peut être trouvé. Il peut être argumenté d'être circulaire. On peut également soutenir que ce paragraphe ne parle pas de une conversion implicite i> "", mais plutôt d'une séquence de conversion implicite i>. C'est-à-dire une séquence de conversions ou i> aucune conversion du tout. Sinon, 0 code> n'a pas pu être "implicitement converti" en une prvalue de type
int code>, ce qui serait faux parce que
int A = 0 code> est bien formé. Je pense que c'est une hypothèse raisonnable à mettre dans le libellé - le paragraphe n'empêche évidemment pas les séquences qui contiennent deux conversions ou plus.
@LitB: Non, mais cela n'apporte pas non plus de mandat que la séquence de conversion entre dans la photo en premier lieu, dans le scénario donné. Vous avez l'étape d'induction triée, mais il manque toujours un cas de base. :)
L'initialisateur a la grammaire de Follwing: dans votre exemple, et un identifiant "est un lvalue si l'entité est une fonction ou une variable" (expressions primaires "5.1 / 4"). P> Donc, dans votre exemple, l'expression à droite du Je ne sais pas quelle est la valeur en sachant que c'est, cependant. P> p> x code> est un
affectation-expression code> qui suit cette chaîne de Productions de la grammaire: p>
= code> est une expression qui se trouve être un
lvalue code>. Cela pourrait être un
rvalue code> bien sûr, mais cela ne doit pas être. Et il n'y a pas de conversion obligatoire de lvalue-to-rvalue. P>
Je ne pense pas que de telles conversions ont lieu. En tout cas, ce sont des types primitifs, mais même si vous aviez des constructeurs non triviaux, ce que vous avez écrit invoquerait la copie, jamais le constructeur de déplacement.
Discussion à chat.stackoverflow.com/transcript/message/847067#847067 peut être pertinent.
@Kerrek: Mais la valeur doit être utilisée. Comment une telle conversion peut-elle pas i> avoir lieu? (Et il n'y a pas de constructeur de mouvement en 2003).
@Tomalak: Je vois ... Alors, c'est juste une chose sémantique à l'intérieur du compilateur, ou la conversion a-t-elle des effets visibles?
@Kerrek: J'espère bien que cela n'a aucun effet!
@TOMALAK: Je pense que si un opérateur d'affectation avait besoin d'une r devale, il serait mentionné en 5.17, et ce n'est pas mentionné.
@Tomalak: À moins que ce soit ce que signifie 5,17 / 2 "en simple affectation (=), la valeur b> de l'expression remplace celle de l'objet mentionné par l'opérande gauche."
@Trutheality: voir, il semble ambigu>. <
@Tomalak: Je pense avoir trouvé la citation pertinente en 8.5 / 14, elle est assez similaire à la citation de 5.17/2 ci-dessus, faisant référence à l'initialisation plutôt que à la mission.