#include <stdio.h> int main() { int i = 10; printf("%d\n", ++(-i)); // <-- Error Here } What is wrong with ++(-i)? Please clarify.
4 Réponses :
Le ++ code> incrémente une variable. (Ou, pour être plus précis, un lvalue em> -quelque chose qui peut apparaître sur le côté L B> EFT d'une expression d'affectation) p>
(- i) code> n'est pas une variable, de sorte qu'il n'a pas de sens d'incrémenter. P>
Je trouve la similitude de variable i> et lvalue i> beaucoup mieux que la variante peut apparaître sur le côté gauche d'une expression d'affectation i>. J'ai vu beaucoup de gens argumenter que vous ne pouvez pas avoir une expression qui donne une constante de lvalue i> parce que cela ne peut pas être utilisé comme le côté gauche d'une affectation (donnée const int & foo (); code>,
foo (); code> est une expression de lvalue, et pourtant vous n'êtes pas autorisé - pour d'autres raisons - de l'affecter)
-I code> génère un temporaire et que vous ne pouvez pas appliquer
++ code> sur un temporaire (généré à la suite d'une expression de rvalue). Pré-augmentation
++ code> nécessite son opérande d'être un lvalue,
-i code> n'est pas un lvalue pour obtenir l'erreur. P>
Je ne pense pas que c'est une réponse correcte. Vous pouvez appliquer ++ code> sur un temporaire: ideone.com/cv9oi
@Nawaz: Pas sur les temporels générés par des expressions de rvalue. Édité mon post.
@Nawaz: Vous êtes autorisé à invoquer des fonctions membres sur les temporaires.
@Prason: Mais vous avez dit que je ne peux pas appliquer ++ code> sur les temporaires générés par des expressions de rvalue, qui est trompeuse, car je peux.
Je pense que Slaks a le terme correct pour cela. Ce ne sont pas des temporaires mais r / lvalues.
++ (a ()) n'est pas une prvalue. (-i) est. (-Je) ne renvoie pas une référence. Vous ne pouvez pas faire ++ (- a ()) non plus.
@Xaade: prvalue code> est un concept C ++ 0x, tandis que nous discutons de C ++ 03. Et je peux faire même
++ (- a ()) code> aussi: Ideone.com/ 361fl
@Nawaz, il est donc formulé de définir des catégories d'expressions. Les mêmes règles s'appliquent à la question de savoir si l'expression a une identité ou non. La seule différence est une question de savoir si les expressions peuvent être déplacées.
@Nawaz: §5.3.2 L'opérande du préfixe ++ est modifié en ajoutant 1 ou défini sur true si elle est bool (cette utilisation est obsolète). L'opérande doit être un lvalue modifiable. Le type de l'opérande doit être un type arithmétique ou un pointeur sur un type d'objet complètement défini. La valeur est la nouvelle valeur de l'opérande; C'est un lvalue. I> L'exemple que vous fournissez est différent en ce qu'il s'agit d'un opérateur de fonction membre et de telle sorte qu'il se comporte comme toute autre fonction membre, et ceux qui ne doivent pas nécessairement être appliqués à une lvalue.
Je changerais simplement le libellé sur "Vous ne pouvez pas appliquer intégré ++ code> à un rvalue" - puisque vous êtes autorisé à appeler des fonctions de membre sur des r devalues de type de classe (c'est-à-dire des temporaires).
@David: Je discutais de la terminologie @prasoon utilisé dans sa réponse: temporaire code> vs
lvalue code> vs
rvalue code>. Utilisation du terme temporaire i> ici est un peu trompeur.
ideone.com/2k3fw . C'est un lvalue maintenant. Par conséquent, une identité peut donc être utilisée pour augmenter. Ce n'est pas parce qu'il n'a pas de variable comme référence, cela ne signifie pas que ce n'est pas un lvalue. Déplacer est un concept C ++ 0X, mais les règles de l / rvalue et qui ont des identités sont les mêmes.
@Nawaz: Je ne pense pas. Vous avez déclaré que la réponse était non convaincante puisque vous pouviez faire quelque chose de similaire avec un membre B> opérateur ++ code>, qui est un problème totalement indépendant. Considérer
struct a {}; Un opérateur ++ (A &); ++ a (); code> ooops ... vous ne pouvez pas appeler
opérateur ++ code> là. Vous changé i> le problème (d'un préincrècement intégré à un préincrècement membre), puis indiqué que cette réponse n'a pas résolu votre problème modifié i>. Et après coup, vous avez expliqué quelle est la différence, vous ne pouvez pas accepter que vous avez commis une erreur. Nous faisons tous des erreurs, c'est ainsi que nous apprenons.
@Nawaz @david @prason Le point de cette discussion est qu'un temporaire peut être incrémenté. Je n'ai pas juste démontré ça.
@David: J'ai dit que l'utilisation du terme temporaire i> est un peu trompeuse. Comment pouvez-vous dire que ce n'est pas trompeur? En outre, la réponse originale était plus trompeuse que celle éditée.
@Nawaz: Ce n'était pas trompeur. Découvrez la question à nouveau. Cela dit-il quelque chose (du tout) sur les types définis par l'utilisateur? Oui?
@Xaade: Vous devez remplacer le principal code> avec
++ (- A ()) code>, il n'y a actuellement aucun temporel dans le programme. Et je n'ai jamais prétendu que vous ne pouvez pas avoir une expression de lvalue faisant référence à une temporaire (il y a de nombreuses façons de le faire), mais je trouve toujours qu'il est toujours amusant que les mêmes personnes encore et encore, et sans vraiment comprendre le nitpick sur les autres juste parce que Ils peuvent écrire un code similaire (non équivalent) qui semble fonctionner. Je aurais beaucoup mieux pris s'il y avait une critique constructive sur la terminologie (je viens de le faire dans Slaks, il y a environ 10 minutes)
@Prason: Si ce n'était pas trompeur, demandez-vous: pourquoi avez-vous modifié la réponse et ajouté ce (généré à la suite d'une expression de rvalue) code>? : P. La modification montre que pendant un moment, même vous pensez que c'était trompeur, et vous avez donc ajouté cela pour rendre votre réponse plus précise et moins trompeuse.
@Xaade: Et il y a beaucoup à Nitpick dans ce commentaire ... la variable i> est toujours trompeur, comme il y a - et vous venez de prouver que ... expressions qui donnent des lvalues qui ne sont pas Variables i>. Mais c'est une discussion complète.
@Nawaz: Votre commentaire exact était: Je ne pense pas que c'est une réponse correcte. Vous pouvez appliquer ++ sur un temporaire: ideone.com/cv9oi i>. Cela ne dit pas que vous trouvez temporaire i> trompeur, mais que vous pensez que la réponse est erronée parce que en transformant le problème en appelez une fonction membre i> Vous pouvez appeler une fonction de membre sur un temporaire. Encore une fois, l'utilisation de ce code ne indique même pas que vous parlez de la différence de temporaire i> et rvalue i>, dans les deux cas, les objets sont temporaires i> et Les expressions sont rvalue i> expressions.
@Prason: Cela prouve à nouveau que vous êtes d'accord pour dire que c'était trompeur pour certaines personnes au moins. Je n'ai jamais dit que c'est trompeur pour tout le monde. En fait, rien ne peut être trompeur pour toutes les personnes. C'est toujours pour certaines personnes.
@Nawaz: La raison du bowvote n'avait pas eu de sens pour moi du tout. Vous Généralement B> Ramassez un point et ne pensez même pas à accepter ce que les autres disent (même si vous vous trompez).
@David: Je trouve temporaire i> trompeur, après la réponse de la réponse, je ne peux pas appliquer ++ code> sur un temporaire, ce qui ne va pas, aussi loin que je sache.
@Nawaz: Le contexte était complètement différent. Où dans le poste d'ouverture voyez-vous des types définis utilisés?
@Prason: cela n'a pas eu de sens pour vous. Ça me semble logique. J'ai donné ma raison.
@Prason: Mais ce n'est pas clair de votre réponse que c'est vrai pour ce contexte seulement. Les gens apprennent généralement le concept d'un exemple et tentent d'appliquer cela dans l'autre exemple. C'est ainsi que nous apprenons de nouvelles choses.
@Nawaz: Il n'est pas nécessaire que ce soit clair pour vous. C'est clair pour les autres. : P
@Nawaz: Sérieusement, une horloge cassée donne le bon moment deux fois par jour. La réponse est (et la première version de celle-ci était) assez claire. Il utilise l'expression -i code>, qui donne un temporaire i> de type
int code> et un rvalue i> et il dit aussi que
++ code> nécessite un lvalue i>. Bien que cela puisse être meilleur - cela pourrait éviter de mentionner temporaire, il pourrait spécifier que
++ code> nécessite un lvalue, sauf s'il est remplacé par la fonction de membre de la classe i>, qui est hors de la portée de la question. Cela pourrait être mieux, mais ce n'est pas mal i> par n'importe quel moyen.
@David: Le terme mal code> pourrait être faux ici: P, mais tout ce que je voulais dire, c'est que je pouvais très bien appliquer
++ code> sur temporaire, mais la réponse indique autre chose. La réponse était donc censée contenir peu de mots supplémentaires pour préciser que c'est vrai dans un tel contexte. Sinon, les apprenants agressifs comme moi apprennent souvent des concepts d'un exemple et essayez de l'appliquer dans d'autres exemples; C'est ainsi que la plupart des humains apprennent de nouvelles choses. Comme certains sages ont dit des exemples
sont l'école de l'humanité, ils apprendront à aucun autre. Code> :-)
@Nawaz: Si vous voulez une précision, commencez à appliquer cela à vos commentaires: Je pourrais très bien appliquer ++ code> surchargé en tant que fonction membre dans un type défini par l'utilisateur b> sur un temporaire i>. La question concerne
int code>, ce n'est pas un type défini par l'utilisateur, et il ne demande pas si dans une circonstance sombre complexe, elle peut être appliquée. Si vous voulez une précision à 100%, appliquez-la à vous-même. Le commentaire de @xaade appliquant un
++ intégré code> à un temporaire est accueilli. Par votre propre règle, votre commentaire n'est pas accueilli, car il semble indiquer que
++ code> sur INTS et comme les fonctions membres sont équivalent i>.
@David: Oui. Mais seulement après avoir connu la différence, nous connaissons la différence. Il n'y a aucun moyen de connaître la différence, sans connaître la différence. Tu as ce que j'ai dit? : |
Vous êtes fous. 1. Vous ne pouvez pas incrémenter une rvalue car elle n'a pas d'identité. 2. Vous pouvez incrémenter un lvalu, car il a une identité. 3. Avoir le remplacement de l'opérateur ++ sur un objet vous permet d'appeler une méthode dans un objet même s'il s'agit d'une r devalue, mais cette méthode n'incrément pas, le programmateur peut avoir cette méthode mettant en œuvre les effets d'un incrément.
Ce fil de commentaire semble être beaucoup d'effort pour quelque chose qui pourrait simplement être écrit de manière plus claire et plus compréhensible (qui fonctionne réellement).
@Robert Vous voulez dire comme le mien ci-dessous.
Vous ne pouvez pas incrémenter un temporaire (- i) n'a aucune identité, il n'y a donc rien à référer à cela. Avec rien pour le faire référence, il n'y a aucun moyen de stocker quelque chose dedans. Vous ne pouvez pas vous référer à (-i), par conséquent, vous ne pouvez donc pas l'incrémenter. P> Essayez i = -I + 1 P> #include <stdio.h>
int main()
{
int i = 10;
printf("%d\n", -i + 1); // <-- No Error Here
}
Essayez cela à la place:
#include <stdio.h> int main() { int i = 10; printf("%d\n", (++i) * -1); }
Devrait être --i. ++ i * -1 est -i-1, tandis que --I * -1 est (I-1) * - 1 = -i + 1.
Même si c'est [I> faire quelque chose de raisonnable, je voudrais toujours vous prier de la réécrire d'une manière qui a du sens aux personnes qui vont lire votre code plus tard