Existe-t-il une différence entre ++i
et i++
dans une boucle for
? Est-ce simplement une chose de syntaxe?
a ++ est appelé postfix.
ajouter 1 à a, retourne l'ancienne valeur.
++ a est appelé préfixe.
ajouter 1 à a, retourne la nouvelle valeur.
C #:
string[] items = {"a","b","c","d"};
int i = 0;
foreach (string item in items)
{
Console.WriteLine(++i);
}
Console.WriteLine("");
i = 0;
foreach (string item in items)
{
Console.WriteLine(i++);
}
Sortie:
1
2
3
4
0
1
2
3
Les boucles foreach
et while
dépendent du type d'incrément utilisé. Avec les boucles for comme ci-dessous, cela ne fait aucune différence, car vous n'utilisez pas la valeur de retour de i:
for (int i = 0; i < 5; i++) { Console.Write(i);}
Console.WriteLine("");
for (int i = 0; i < 5; ++i) { Console.Write(i); }
0 1 2 3 4
0 1 2 3 4
Si la valeur évaluée est utilisée, le type d'incrément devient significatif:
int n = 0;
for (int i = 0; n < 5; n = i++) { }
Pré-incrémentation ++ i incrémente la valeur de i et est évaluée à la nouvelle valeur incrémentée.
int i = 3;
int preIncrementResult = ++i;
Assert( preIncrementResult == 4 );
Assert( i == 4 );
Post-incrémentation i ++ incrémente la valeur de i et correspond à la valeur d'origine non incrémentée.
int i = 3;
int postIncrementResult = i++;
Assert( postIncrementtResult == 3 );
Assert( i == 4 );
En C++, la pré-incrémentation est généralement préférable lorsque vous pouvez utiliser l'un ou l'autre.
En effet, si vous utilisez la post-incrémentation, le compilateur peut être obligé de générer du code créant une variable temporaire supplémentaire. En effet, les valeurs précédentes et nouvelles de la variable en cours d'incrémentation doivent être conservées quelque part car elles peuvent être nécessaires ailleurs dans l'expression en cours d'évaluation.
Donc, en C++ au moins, il peut y avoir une différence de performance qui détermine votre choix d'utilisation.
Cela pose principalement un problème lorsque la variable à incrémenter est un type défini par l'utilisateur avec un opérateur ++ surchargé. Pour les types primitifs (int, etc.), il n'y a pas de différence de performance. Toutefois, il vaut la peine de s’en tenir à l’opérateur de pré-incrémentation à moins que l’opérateur de post-incrément ne soit vraiment ce qu’il faut.
Il y a un peu plus de discussion ici:
https://web.archive.org/web/20170405054235/http://fr.allexperts.com/q/C-1040/Increment-operators.htm
En C++, si vous utilisez STL, vous utilisez peut-être des boucles for avec des itérateurs. Ceux-ci ont principalement des opérateurs ++ surchargés, il est donc judicieux de rester sur la pré-incrémentation. Les compilateurs sont de plus en plus intelligents et les plus récents peuvent effectuer des optimisations sans aucune différence de performances, en particulier si le type à incrémenter est défini en ligne dans le fichier d’en-tête (comme le sont souvent les implémentations STL) afin que le compilateur puisse voir comment. la méthode est mise en œuvre et peut alors savoir quelles optimisations peuvent être effectuées en toute sécurité. Même dans ce cas, il est probablement utile de s'en tenir au pré-incrément, car les boucles sont exécutées de nombreuses fois et cela signifie qu'une légère pénalité de performance pourrait bientôt être amplifiée.
Dans d'autres langages tels que C #, où l'opérateur ++ ne peut pas être surchargé, il n'y a pas de différence de performances. Utilisés dans une boucle pour faire avancer la variable de boucle, les opérateurs de pré-incrémentation et de post-incrémentation sont équivalents.
Correction: la surcharge ++ en C # est autorisée. Il semble cependant que par rapport au C++, en c #, vous ne pouvez pas surcharger les versions antérieure et postérieure de manière indépendante. Donc, je suppose que si le résultat de l'appel de ++ en C # n'est pas affecté à une variable ou utilisé dans le cadre d'une expression complexe, le compilateur réduirait les versions antérieure et postérieure de ++ au code qui fonctionne de manière équivalente.
En C #, il n'y a pas de différence lorsqu'il est utilisé dans une boucle for.
for (int i = 0; i < 10; i++) { Console.WriteLine(i); }
sort la même chose que
for (int i = 0; i < 10; ++i) { Console.WriteLine(i); }
Comme d'autres l'ont fait remarquer, lorsqu'ils sont utilisés en général, i ++ et ++ i présentent une différence subtile mais significative:
int i = 0;
Console.WriteLine(i++); // Prints 0
int j = 0;
Console.WriteLine(++j); // Prints 1
i ++ lit la valeur de i puis l'incrémente.
++ i incrémente la valeur de i puis la lit.
La question est:
Existe-t-il une différence entre ++ i et i ++ dans une boucle for?
La réponse est: No.
Pourquoi chaque réponse doit-elle entrer dans des explications détaillées sur l'incrémentation avant et après, alors que cela n'est même pas demandé?
Cette boucle for:
for (int i = 0; // Initialization
i < 5; // Condition
i++) // Increment
{
Output(i);
}
Traduirait ce code sans utiliser de boucles:
int i = 0; // Initialization
loopStart:
if (i < 5) // Condition
{
Output(i);
i++ or ++i; // Increment
goto loopStart;
}
Maintenant, est-ce important si vous mettez i++
ou ++i
comme incrément ici? Non, ce n'est pas le cas car la valeur de retour de l'opération d'incrémentation est non significative. i
sera incrémenté APRÈS l'exécution du code à l'intérieur du corps de la boucle for.
Puisque vous demandez la différence dans une boucle, je suppose que vous voulez dire
for(int i=0; i<10; i++)
...;
Dans ce cas, vous n'avez aucune différence dans la plupart des langues: la boucle se comporte de la même manière que vous écriviez i++
et ++i
. En C++, vous pouvez écrire vos propres versions des opérateurs ++, et vous pouvez définir des significations distinctes pour eux, si la i
est d'un type défini par l'utilisateur (votre propre classe, par exemple).
La raison pour laquelle cela n'a pas d'importance ci-dessus est que vous n'utilisez pas la valeur de i++
. Une autre chose est quand vous faites
for(int i=0, a = 0; i<10; a = i++)
...;
Maintenant, il y a est une différence, parce que, comme d'autres le soulignent, i++
signifie incrément, mais évalue à la valeur précédente, mais ++i
signifie - incrémente, mais évalue à i
(ainsi, la valeur sera évaluée). Dans le cas ci-dessus, a
se voit attribuer la valeur précédente de i, tandis que i est incrémenté.
Comme ce code l'indique (voir le MSIL disséminé dans les commentaires), le compilateur C # 3 ne fait aucune distinction entre i ++ et ++ i dans une boucle for. Si la valeur de i ++ ou ++ i était prise, il y aurait certainement une différence (cela a été compilé dans Visutal Studio 2008/Release Build):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PreOrPostIncrement
{
class Program
{
static int SomethingToIncrement;
static void Main(string[] args)
{
PreIncrement(1000);
PostIncrement(1000);
Console.WriteLine("SomethingToIncrement={0}", SomethingToIncrement);
}
static void PreIncrement(int count)
{
/*
.method private hidebysig static void PreIncrement(int32 count) cil managed
{
// Code size 25 (0x19)
.maxstack 2
.locals init ([0] int32 i)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: br.s IL_0014
IL_0004: ldsfld int32 PreOrPostIncrement.Program::SomethingToIncrement
IL_0009: ldc.i4.1
IL_000a: add
IL_000b: stsfld int32 PreOrPostIncrement.Program::SomethingToIncrement
IL_0010: ldloc.0
IL_0011: ldc.i4.1
IL_0012: add
IL_0013: stloc.0
IL_0014: ldloc.0
IL_0015: ldarg.0
IL_0016: blt.s IL_0004
IL_0018: ret
} // end of method Program::PreIncrement
*/
for (int i = 0; i < count; ++i)
{
++SomethingToIncrement;
}
}
static void PostIncrement(int count)
{
/*
.method private hidebysig static void PostIncrement(int32 count) cil managed
{
// Code size 25 (0x19)
.maxstack 2
.locals init ([0] int32 i)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: br.s IL_0014
IL_0004: ldsfld int32 PreOrPostIncrement.Program::SomethingToIncrement
IL_0009: ldc.i4.1
IL_000a: add
IL_000b: stsfld int32 PreOrPostIncrement.Program::SomethingToIncrement
IL_0010: ldloc.0
IL_0011: ldc.i4.1
IL_0012: add
IL_0013: stloc.0
IL_0014: ldloc.0
IL_0015: ldarg.0
IL_0016: blt.s IL_0004
IL_0018: ret
} // end of method Program::PostIncrement
*/
for (int i = 0; i < count; i++)
{
SomethingToIncrement++;
}
}
}
}
Un (++ i) est préincrémenté, un (i ++) est postincrémenté. La différence réside dans la valeur renvoyée immédiatement par l'expression.
// Psuedocode
int i = 0;
print i++; // Prints 0
print i; // Prints 1
int j = 0;
print ++j; // Prints 1
print j; // Prints 1
Edit: Woops, a complètement ignoré le côté boucle des choses. Il n'y a pas de différence réelle entre les boucles for quand il s'agit de la partie "étape" (pour (...; ...;)), mais cela peut entrer en jeu dans d'autres cas.
Voici un exemple Java et le Byte-Code, post- et preIncrement ne montrent aucune différence dans le Bytecode:
public class PreOrPostIncrement {
static int somethingToIncrement = 0;
public static void main(String[] args) {
final int rounds = 1000;
postIncrement(rounds);
preIncrement(rounds);
}
private static void postIncrement(final int rounds) {
for (int i = 0; i < rounds; i++) {
somethingToIncrement++;
}
}
private static void preIncrement(final int rounds) {
for (int i = 0; i < rounds; ++i) {
++somethingToIncrement;
}
}
}
Et maintenant, le byte-code (javap -private -c PreOrPostIncrement):
public class PreOrPostIncrement extends Java.lang.Object{
static int somethingToIncrement;
static {};
Code:
0: iconst_0
1: putstatic #10; //Field somethingToIncrement:I
4: return
public PreOrPostIncrement();
Code:
0: aload_0
1: invokespecial #15; //Method Java/lang/Object."<init>":()V
4: return
public static void main(Java.lang.String[]);
Code:
0: sipush 1000
3: istore_1
4: sipush 1000
7: invokestatic #21; //Method postIncrement:(I)V
10: sipush 1000
13: invokestatic #25; //Method preIncrement:(I)V
16: return
private static void postIncrement(int);
Code:
0: iconst_0
1: istore_1
2: goto 16
5: getstatic #10; //Field somethingToIncrement:I
8: iconst_1
9: iadd
10: putstatic #10; //Field somethingToIncrement:I
13: iinc 1, 1
16: iload_1
17: iload_0
18: if_icmplt 5
21: return
private static void preIncrement(int);
Code:
0: iconst_0
1: istore_1
2: goto 16
5: getstatic #10; //Field somethingToIncrement:I
8: iconst_1
9: iadd
10: putstatic #10; //Field somethingToIncrement:I
13: iinc 1, 1
16: iload_1
17: iload_0
18: if_icmplt 5
21: return
}
Il n'y a pas de différence si vous n'utilisez pas la valeur après avoir incrémenté la boucle.
for (int i = 0; i < 4; ++i){
cout<<i;
}
for (int i = 0; i < 4; i++){
cout<<i;
}
Les deux boucles vont imprimer 0123.
Mais la différence vient lorsque vous utilisez la valeur après incrément/décrément dans votre boucle comme ci-dessous:
Boucle de pré-incrémentation:
for (int i = 0,k=0; i < 4; k=++i){
cout<<i<<" ";
cout<<k<<" ";
}
Sortie: 0 0 1 1 2 2 3 3
Boucle post-incrémentation:
for (int i = 0, k=0; i < 4; k=i++){
cout<<i<<" ";
cout<<k<<" ";
}
Sortie: 0 0 1 0 2 1 3 2
J'espère que la différence est claire en comparant les résultats. Il convient de noter ici que l’incrément/décrément est toujours effectué à la fin de la boucle for et que, par conséquent, les résultats peuvent être expliqués.
Oui il y a. La différence est dans la valeur de retour. La valeur de retour de "++ i" sera la valeur after incrementing i. Le retour de "i ++" sera la valeur avant incrémentée. Cela signifie que le code qui ressemble à ce qui suit:
int a = 0;
int b = ++a; // a is incremented and the result after incrementing is saved to b.
int c = a++; // a is incremented again and the result before incremening is saved to c.
Par conséquent, a serait 2 et b et c seraient chacun 1.
Je pourrais réécrire le code comme ceci:
int a = 0;
// ++a;
a = a + 1; // incrementing first.
b = a; // setting second.
// a++;
c = a; // setting first.
a = a + 1; // incrementing second.
Il n'y a pas de différence réelle dans les deux cas, 'i
' sera incrémenté de 1.
Mais il y a une différence lorsque vous l'utilisez dans une expression, par exemple:
int i = 1;
int a = ++i;
// i is incremented by one and then assigned to a.
// Both i and a are now 2.
int b = i++;
// i is assigned to b and then incremented by one.
// b is now 2, and i is now 3
++ i et i ++ ne se limitent pas aux boucles et aux différences de performances. ++ i renvoie une valeur l et i ++ renvoie une valeur r. Sur cette base, il y a beaucoup de choses que vous pouvez faire pour (++ i) mais pas pour (i ++).
1- It is illegal to take the address of post increment result. Compiler won't even allow you.
2- Only constant references to post increment can exist, i.e., of the form const T&.
3- You cannot apply another post increment or decrement to the result of i++, i.e., there is no such thing as I++++. This would be parsed as ( i ++ ) ++ which is illegal.
4- When overloading pre-/post-increment and decrement operators, programmers are encouraged to define post- increment/decrement operators like:
T& operator ++ ( )
{
// logical increment
return *this;
}
const T operator ++ ( int )
{
T temp( *this );
++*this;
return temp;
}
Je ne comprends pas pourquoi les gens peuvent écrire l'expression d'incrémentation dans une boucle for tant que i ++.
Dans une boucle for, lorsque le troisième composant est une simple instruction d'incrémentation, comme dans
for (i=0; i<x; i++)
ou
for (i=0; i<x; ++i)
il n'y a pas de différence dans les exécutions résultantes.
En javascript en raison de ce qui suit i ++ peut être préférable d'utiliser:
var i=1;
alert(i++); // before, 1. current, 1. after, 2.
alert(i); // before, 2. current, 2. after, 2.
alert(++i); // before, 2. current, 3 after, 3.
Alors que les tableaux (je pense que tous) et quelques autres fonctions et appels utilisent 0 comme point de départ, vous devez définir i sur -1 pour que la boucle fonctionne avec le tableau lors de l'utilisation de ++ i.
Lors de l'utilisation de i ++, la valeur suivante utilisera la valeur augmentée. Vous pourriez dire que i ++ est la façon dont les humains comptent, car vous pouvez commencer avec un .
Comme @ Jon B dit, il n'y a pas de différence dans une boucle for.
Mais dans une boucle while
ou do...while
, vous pouvez trouver certaines différences si vous effectuez une comparaison avec le ++i
ou i++
while(i++ < 10) { ... } //compare then increment
while(++i < 10) { ... } //increment then compare
Il peut y avoir une différence pour les boucles. C'est l'application pratique de post/pré-incrémentation.
int i = 0;
while(i++ <= 10) {
Console.Write(i);
}
Console.Write(System.Environment.NewLine);
i = 0;
while(++i <= 10) {
Console.Write(i);
}
Console.ReadLine();
Alors que le premier compte jusqu'à 11 et boucle 11 fois, le second ne le fait pas.
Généralement, cela est plutôt utilisé dans un simple while (x--> 0); - - Boucle pour parcourir, par exemple, tous les éléments d'un tableau (en excluant les constructions foreach ici).
Ils augmentent tous les deux le nombre. ++i
est équivalent à i = i + 1
.
i++
et ++i
sont très similaires mais pas exactement les mêmes. Les deux incrémentent le nombre, mais ++i
incrémente le nombre avant l'évaluation de l'expression actuelle, tandis que i++
incrémente le nombre après l'évaluation de l'expression.
int i = 3;
int a = i++; // a = 3, i = 4
int b = ++a; // b = 4, a =
Vérifiez ce lien .
Oui, il y a une différence entre ++i
et i++
dans une boucle for
, bien que dans des cas d'utilisation inhabituels; lorsqu'une variable de boucle avec l'opérateur d'incrémentation/décrémentation est utilisée dans le bloc for ou dans l'expression du test de boucle, ou avec l'une des variables de boucle . Non, ce n'est pas simplement une question de syntaxe.
Comme i
dans un code, cela signifie évaluer l'expression i
et l'opérateur ne signifie pas une évaluation, mais simplement une opération;
++i
signifie la valeur d'incrément de i
de 1 et plus tard, évaluer i
,i++
signifie évaluer i
et incrémenter plus tard de i
par 1.Donc, ce qui est obtenu à partir de chacune des deux expressions diffère parce que ce qui est évalué diffère dans chacune. Tous les mêmes pour --i
et i--
Par exemple;
let i = 0
i++ // evaluates to value of i, means evaluates to 0, later increments i by 1, i is now 1
0
i
1
++i // increments i by 1, i is now 2, later evaluates to value of i, means evaluates to 2
2
i
2
Dans les cas d'utilisation inhabituels, cependant, l'exemple suivant semble utile ou pas, peu importe, cela montre une différence
for(i=0, j=i; i<10; j=++i){
console.log(j, i)
}
for(i=0, j=i; i<10; j=i++){
console.log(j, i)
}