J'ai donc lu sur lvalue et rvalues et je suis un peu confus quant à la différence entre ++x
et x++
en ce qui concerne cette catégorisation.
Pourquoi ++x
une valeur et x++
une valeur?
J'ai donc lu sur lvalue et rvalues et je suis un peu confus quant à la différence entre ++x
et x++
en ce qui concerne cette catégorisation.
Pourquoi ++x
une valeur et x++
une valeur?
++x
renvoie une référence à l'objet que vous incrémenté, où qu' x++
renvoie une copie temporaire de l' x
s'ancienne valeur.
Au moins ce serait la façon "normale" par la mise en œuvre de ces opérateurs par la convention. Et tous les types intégrés fonctionnent de cette manière. Et si vous avez lu sur lvalues / rvalues vous verriez alors que depuis le préfixe de l'opérateur renvoie le nom de l'objet lui-même, il serait être une lvalue, où, comme le postfix opérateur renvoie une copie d'un local temporaire, qui serait reconnue comme une rvalue.
Remarque: en outre, nous avons prvalues, xvalues et ces maintenant, donc, techniquement, il est un peu plus compliqué de nos jours. Regardez ici pour plus d'info.
C++ (par opposition à C) est consacré lvalue-la préservation de la langue: elle s'efforce laborieusement de préserver la "lvalueness" d'une expression chaque fois que cela est possible.
Il est très facile de préserver le "lvalueness" de pré-incrémentation: il suffit d'incrémenter le opérande et le retourner comme une lvalue. Fait. Le retour de l'lvalue contiendra exactement le résultat qu'il est censé contenir: la nouvelle (incrémenté) de la valeur de l'opérande.
Et dans le même temps, il est pratiquement impossible de conserver la "lvalueness" de la post-incrémentation: par définition, le résultat de la post-incrémentation est l'ancienne (d'origine) de la valeur de l'opérande. Si vous essayez de revenir une lvalue de la post-incrémentation, vous devez en quelque sorte simultanément de s'assurer de deux choses: 1) la lvalue est incrémenté, 2) le code d'appel voit la vieille valeur quand elle regarde dans la même lvalue (!). Cette combinaison d'exigences est donc contradictoire qui est pratiquement impossible à mettre en œuvre en C++ d'un modèle d'objet.
Afin de mettre en œuvre une bonne post-incrémentation un comportement doit s'assurer que le code appelant n'a pas l'air directement dans l'opérande, mais plutôt les regards dans certains conceptuel ou physique "proxy" qui rend le code appelant à "voir" la vieille valeur de l'opérande. Cette procuration peut être un objet temporaire qui retient l'ancienne valeur. Ou que la procuration peut être quelque chose qui génère l'ancienne valeur à la volée en soustrayant 1
de la nouvelle valeur. En tout cas, que le proxy est ce qui empêche le code d'appel de l'accès à l'original de la lvalue.
C'est pourquoi le C++ prend avantage de la facilement réalisables occasion de la préserver "lvalueness" de la pré-incrémentation, mais concède à l'impossibilité de réaliser la même chose avec la post-incrémentation. Dans le cas de la post-incrémentation, il n'est tout simplement pas la peine de dévier de la norme classique C de comportement, ce qui tend à jeter "lvalueness" rapidement et avec plaisir.
Peut-être que l'écriture du fonctionnement en pseudo-code des opérateurs pour int
rend plus clair:
préfixe:
int& Prefix(int& val)
{
int& value = val;
value += 1;
return value;
}
suffixe:
int Postfix(int& val)
{
int oldValue = val;
val += 1;
return oldValue;
}
La différence réside dans ce qui est retourné par les deux opérateurs, un par valeur et un par référence.
Pourquoi est - ++x une lvalue
Je devine que c'est une lvalue, car il peut être.
++x
il peut être considéré comme((x = x + 1), x) // Increment x. Then evaluate to the value of x
ou
((x += 1), x) // Increment x. Then evaluate to the value of x
Il est logique d'évaluer
++x
pour une lvalue.x++ une rvalue?
Car il ne peut pas être une lvalue.
x++
il peut être considéré comme((unnamed_variable = x), (x = x + 1), unnamed_variable)
ou
((unnamed_variable = x), (x += 1), unnamed_variable)
x++
correspond à la valeur d'avant -x
est incrémenté. Depuis il n'y a pas de variable qui permet de stocker cette valeur, il ne peut pas être une lvalue.
Pour les types intégrés, tels que l' int
, x++
rendements de l'ancienne valeur de x
. Il n'y a pas de stockage associé, de sorte qu'il serait impossible pour l'expression être une lvalue.
En C, ++x
a abouti à la nouvelle valeur de x
(et n'était pas une lvalue). Depuis l'objet x
contient la même valeur, il est possible d'avoir ++x
désigner l'objet x
(c'est à dire être une lvalue). C'est des fonctionnalités supplémentaires par rapport à ce qui donne une rvalue, et le concepteur de C++ décidé que ce serait une amélioration de la langue.
Pour les types de classe, il est possible de surcharge d'un opérateur de telle manière que l'utilisation de l'opérateur peut donner une lvalue, value, ou prvalue. Cependant, il est considéré de bon ton de faire des opérateurs surchargés ont les mêmes sémantique à des opérateurs, ce qui est pourquoi il est normal pour les gens de la surcharge en ++x
de rendement une lvalue et à surcharger x++
pour le rendement d'une rvalue.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.