J'apprends actuellement C ++ et j'ai appris l'incrémentation il y a quelque temps. Je sais que vous pouvez utiliser "++ x" pour faire l'incrémentation avant et "x ++" pour le faire après.
Pourtant, je ne sais vraiment pas quand utiliser l'un ou l'autre des deux ... Je n'ai jamais vraiment utilisé "++ x" et les choses ont toujours bien fonctionné jusqu'à présent - alors, quand dois-je l'utiliser?
Exemple: Dans une boucle for, quand est-il préférable d'utiliser "++ x"?
Aussi, quelqu'un pourrait-il expliquer exactement comment fonctionnent les différentes incrémentations (ou décrémentations)? J'apprécierai vraiment cela.
la source
x++
est une rvalue avec la valeurx
avant incrément,x++
est une lvalue avec la valeurx
après un incrément. Aucune des deux expressions ne garantit que la valeur incrémentée réelle est stockée dans x, il est seulement garanti que cela se produit avant le point de séquence suivant. «après le traitement de l'instruction courante» n'est pas strictement précis car certaines expressions ont des points de séquence et certaines instructions sont des instructions composées.Scott Meyers vous dit de préférer le préfixe sauf dans les cas où la logique dicterait que le suffixe est approprié.
"C ++ plus efficace" item # 6 - c'est une autorité suffisante pour moi.
Pour ceux qui ne possèdent pas le livre, voici les citations pertinentes. À partir de la page 32:
Et à la page 34:
la source
i++
ou++i
, le code généré est le même.++x
etx++
compte réellement, il est beaucoup plus important que vous utilisiez réellement un compilateur capable d'optimiser complètement et correctement l'une ou l'autre version, quel que soit le le contexte. «Depuis que j'utilise ce vieux marteau merdique, je ne peux enfoncer des clous qu'à un angle de 43,7 degrés» est un mauvais argument pour construire une maison en enfonçant des clous à seulement 43,7 degrés. Utilisez un meilleur outil.De cppreference lors de l'incrémentation des itérateurs:
Le pré-incrémentation ne génère pas l'objet temporaire. Cela peut faire une différence significative si votre objet est coûteux à créer.
la source
Je veux juste remarquer que le code généré est souvent le même si vous utilisez l'incrémentation pré / post où la sémantique (de pré / post) n'a pas d'importance.
exemple:
pre.cpp:
post.cpp:
_
la source
std::map::iterator
? Bien sûr, les deux opérateurs sont différents, mais je suis curieux de savoir si le compilateur optimisera le suffixe en préfixe si le résultat n'est pas utilisé. Je ne pense pas que ce soit autorisé - étant donné que la version postfix pourrait contenir des effets secondaires.La chose la plus importante à garder à l'esprit, imo, est que x ++ doit renvoyer la valeur avant que l'incrément n'ait réellement lieu - par conséquent, il doit faire une copie temporaire de l'objet (pré-incrémentation). C'est moins efficace que ++ x, qui est incrémenté sur place et renvoyé.
Une autre chose à mentionner, cependant, est que la plupart des compilateurs seront en mesure d'optimiser ces choses inutiles lorsque cela est possible, par exemple, les deux options conduiront au même code ici:
la source
Je suis d'accord avec @BeowulfOF, mais pour plus de clarté, je recommanderais toujours de diviser les déclarations afin que la logique soit absolument claire, c'est-à-dire:
ou
Donc, ma réponse est que si vous écrivez un code clair, cela devrait rarement avoir une importance (et si cela compte, votre code n'est probablement pas assez clair).
la source
Je voulais juste souligner à nouveau que ++ x devrait être plus rapide que x ++, (surtout si x est un objet d'un type arbitraire), donc à moins que cela ne soit nécessaire pour des raisons logiques, ++ x devrait être utilisé.
la source
Vous avez bien expliqué la différence. Cela dépend simplement si vous voulez que x s'incrémente avant chaque exécution d'une boucle, ou après cela. Cela dépend de la logique de votre programme, de ce qui est approprié.
Une différence importante en ce qui concerne les itérateurs STL (qui implémentent également ces opérateurs) est qu'il ++ crée une copie de l'objet vers lequel l'itérateur pointe, puis incrémente, puis retourne la copie. ++, d'autre part, l'incrémentation est d'abord effectuée, puis renvoie une référence à l'objet vers lequel l'itérateur pointe maintenant. Ceci est principalement pertinent lorsque chaque bit de performance compte ou lorsque vous implémentez votre propre itérateur STL.
Edit: correction du mélange de notation de préfixe et de suffixe
la source
Exemple 1:
Lorsque plusieurs valeurs sont mises en cascade avec << en utilisant cout, les calculs (le cas échéant) ont lieu de droite à gauche mais l'impression a lieu de gauche à droite, par exemple (si val est initialement 10)
se traduira par
Exemple 2:
Dans Turbo C ++, si plusieurs occurrences de ++ ou (sous n'importe quelle forme) sont trouvées dans une expression, alors tout d'abord toutes les formes de préfixes sont calculées puis l'expression est évaluée et enfin les formes de suffixe sont calculées, par exemple,
Sa sortie dans Turbo C ++ sera
Alors que sa sortie dans le compilateur moderne sera (car ils suivent strictement les règles)
expressions varient d'un compilateur à l'autre.
la source
La compréhension de la syntaxe du langage est importante lorsque l'on considère la clarté du code. Pensez à copier une chaîne de caractères, par exemple avec post-incrémentation:
Nous voulons que la boucle s'exécute en rencontrant le caractère zéro (qui teste false) à la fin de la chaîne. Cela nécessite de tester la valeur avant l'incrémentation et également d'incrémenter l'index. Mais pas nécessairement dans cet ordre - un moyen de coder ceci avec le pré-incrément serait:
C'est une question de goût qui est plus claire et si la machine a une poignée de registres, les deux devraient avoir un temps d'exécution identique, même si a [i] est une fonction qui coûte cher ou qui a des effets secondaires. Une différence significative pourrait être la valeur de sortie de l'indice.
la source