Différence entre i++ et ++i dans une boucle?
y a-t-il une différence entre ++i
et i++
dans une boucle for
? Est-ce simplement une syntaxe chose?
21 réponses
A++ est connu sous le nom de postfix.
ajouter 1 à un, retourne l'ancienne valeur.
++a est appelé préfixe.
ajouter 1 à un, renvoie 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 que vous utilisez. Avec pour boucles comme ci-dessous cela ne fait aucune différence puisque 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, alors le type d'accroissement devient significatif:
int n = 0;
for (int i = 0; n < 5; n = i++) { }
Pré-incrémentation ++i incrémente la valeur de i et renvoie 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 évalue la non-valeur incrémentée.
int i = 3;
int postIncrementResult = i++;
Assert( postIncrementtResult == 3 );
Assert( i == 4 );
en C++, le pré-incrément est généralement préféré là où vous pouvez utiliser l'un ou l'autre.
C'est parce que si vous utilisez post-increment, il peut exiger du compilateur de générer du code qui crée une variable temporaire supplémentaire. C'est parce que les valeurs précédentes et nouvelles de la variable incrémentée doivent être maintenues quelque part parce qu'elles peuvent être nécessaires ailleurs dans l'expression évaluée.
donc, en C++ au moins, il peut y avoir une différence de performance qui guide votre choix.
il s'agit principalement d'un problème lorsque la variable étant incrémenté est un type défini par l'utilisateur avec un substituée ++ opérateur. Pour les types primitifs (int, etc) il n'y a pas de différence de performance. Mais, il vaut la peine de s'en tenir à l'opérateur de pré-incrément comme ligne directrice à moins que l'opérateur de post-incrément est certainement ce qui est nécessaire.
il y a d'autres discussions ici:
https://web.archive.org/web/20170405054235/http://en.allexperts.com/q/C-1040/Increment-operators.htm
en C++ si vous utilisez STL, alors vous pouvez utiliser pour les boucles avec des itérateurs. Ceux-ci ont principalement dépassé les opérateurs++, donc s'en tenir au pré-incrément est une bonne idée. Les compilateurs deviennent plus intelligents tout le temps, et les plus récents peuvent être en mesure d'effectuer des optimisations qui signifient qu'il n'y a aucune différence de performance - surtout si le type étant incrémenté est défini en ligne dans le fichier d'en-tête (comme les implémentations STL sont souvent) de sorte que le compilateur peut voir comment la méthode est mis en œuvre et peut ensuite savoir quelles optimisations sont sûres à effectuer. Même ainsi, il est probablement encore intéressant de s'en tenir au pré-incrément parce que les boucles sont exécutées beaucoup de fois et cela signifie qu'une petite pénalité de performance pourrait bientôt être amplifiée.
dans d'autres langues comme le C# où l'opérateur ++ ne peut pas être surchargé, il n'y a pas de différence de performances. Utilisé dans une boucle pour faire avancer la variable boucle, les opérateurs de pré et post increment sont équivalent.
Correction: la surcharge ++ en C# est autorisée. Il semble cependant que par rapport à C++, en c# on ne peut pas surcharger les versions pré et post indépendamment. Donc, je suppose que si le résultat de l'appel ++ en C# n'est pas assigné à une variable ou utilisé dans le cadre d'une expression complexe, alors le compilateur réduirait les versions pré et post 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 (int i = 0; i < 10; i++) { Console.WriteLine(i); }
produit la même chose que
for (int i = 0; i < 10; ++i) { Console.WriteLine(i); }
Comme d'autres l'ont souligné, lorsqu'il est utilisé en général i++ et ++j'ai une subtile différence significative:
int i = 0;
Console.WriteLine(i++); // Prints 0
int j = 0;
Console.WriteLine(++j); // Prints 1
i++ lit la valeur de i incrémente.
++i incrémente la valeur de i, puis le lit.
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 pas de différence dans la plupart des langues: la boucle se comporte de la même façon, 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 le i
est d'un type défini par l'utilisateur (votre propre classe, par exemple).
la raison pourquoi il n'a pas d'importance parce 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, là est une différence, parce que comme d'autres soulignent, i++
signifie incrément, mais évaluer à la valeur précédente , mais ++i
signifie incrément, mais évaluer à i
(ainsi il évaluerait à la nouvelle valeur). Dans le cas ci-dessus, a
se voit attribuer la valeur précédente de i, tandis que i est incrémenté.
la question Est:
y a-t-il une différence entre ++i et i++ dans une boucle for?
la réponse est: Non .
Pourquoi est-ce que toutes les autres réponses doivent aller dans des explications détaillées sur l'incrémentation avant et après quand ce n'est même pas demandé?
-boucle:
for (int i = 0; // Initialization
i < 5; // Condition
i++) // Increment
{
Output(i);
}
se traduirait par ce code sans en utilisant des boucles:
int i = 0; // Initialization
loopStart:
if (i < 5) // Condition
{
Output(i);
i++ or ++i; // Increment
goto loopStart;
}
quelle importance si vous mettez i++
ou ++i
à L'incrément ici? Non il ne s'agit pas de car la valeur de retour de l'opération d'incrément est insignifiante. i
sera incrémenté après l'exécution du code qui est dans le for-loop-body.
comme le montre ce code (voir le MSIL dissemblable 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 post-incrément. La différence est dans quelle valeur est immédiatement retournée de 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: Oups, totalement ignoré la boucle côté des choses. Il n'y a pas de différence réelle dans les boucles quand il s'agit de la partie 'step' (pour(...; ...; )), mais il peut entrer en jeu dans les autres cas.
voici un Java-Sample et le Byte-Code, post-et pré-incrément 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 pour le byte-code (javap-private-c Preorpost increment):
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 incrément dans la boucle.
for (int i = 0; i < 4; ++i){
cout<<i;
}
for (int i = 0; i < 4; i++){
cout<<i;
}
les deux boucles imprimeront 0123.
mais la différence vient quand vous utilisez la valeur après incrément / décrément dans votre boucle comme ci-dessous:
Boucle De Pré-Incrément:
for (int i = 0,k=0; i < 4; k=++i){
cout<<i<<" ";
cout<<k<<" ";
}
sortie: 0 0 1 1 2 2 3 3
Boucle De Post-Incrément:
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 la sortie. Le Point à noter ici est l'incrément/décrément est toujours effectué à la fin de la boucle et par conséquent les résultats peuvent être expliqués.
Oui, il y en a. La différence réside dans la valeur de retour. La valeur de retour de "++i" sera la valeur après l'incrémentation de i. Le retour de "i++" sera la valeur avant incrémentation. 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.
donc, a serait 2, et b et c serait 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 quand 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
il y a plus de to ++i et i++ que des boucles et des différences de performance. ++renvoie une valeur l et i++ renvoie une valeur R. Basé sur ceci, il y a beaucoup de choses que vous pouvez faire à ( ++i ) mais pas à ( 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;
}
en javascript en raison de l'i++ suivant peut être mieux 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 devriez définir i à -1 pour faire fonctionner la boucle avec le tableau en utilisant ++i .
en utilisant i++ la valeur suivante utilisera la valeur augmentée. Vous pourriez dire i++ est la façon dont les humains compte, parce que tu peux commencer avec un 0 .
je me demande pourquoi les gens écrivent l'expression increment dans for-loop comme I++.
dans une boucle for, lorsque le troisième composant est un simple incrément, 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.
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 pourriez trouver quelques différences si vous faites 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 du post/pré-incrément.
int i = 0;
while(i++ <= 10) {
Console.Write(i);
}
Console.Write(System.Environment.NewLine);
i = 0;
while(++i <= 10) {
Console.Write(i);
}
Console.ReadLine();
pendant que le premier compte à 11 et boucle 11 fois, le second ne fait pas.
la plupart du temps Ceci est plutôt utilisé dans un moment simple(x-- > 0 ) ; - - boucle pour itérer par exemple tous les éléments d'un tableau (exemptant foreach-constructions ici).
ils augmentent tous les deux le nombre. ++i
est l'équivalent de i = i + 1
.
i++
et ++i
sont très semblables, mais pas exactement le même. Tous les deux incrémentent le nombre, mais ++i
incrémente le nombre avant que l'expression courante soit évaluée, tandis que i++
incrémente le nombre après que l'expression est évaluée.
int i = 3;
int a = i++; // a = 3, i = 4
int b = ++a; // b = 4, a =
Vérifier ce lien .
Oui, il y a une différence entre ++i
et i++
dans un for
en boucle, bien que dans des cas d'utilisation; lorsqu'une variable de boucle avec incrément/décrément de l'opérateur est utilisé dans le bloc ou à l'intérieur de la boucle de test de l'expression , ou avec l'une des variables de boucle . Non ce n'est pas simplement une syntaxe chose.
comme i
dans un code signifie évaluer l'expression i
et l'opérateur ne signifie pas une évaluation, mais juste d'une opération;
-
++i
signifie la valeur d'incrément dei
par 1 et, plus tard, d'évaluer lesi
, -
i++
signifie " évalueri
et, plus tard, la valeur d'incrément dei
par 1.
ainsi, ce qui est obtenu de chacune des deux expressions diffèrent parce que ce qui est évalué diffère dans chacune. Tout de même 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 inhabituelle, cependant l'exemple suivant semble utile ou pas n'importe pas, il 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)
}
pour i
de types définis par l'utilisateur, ces opérateurs pourraient (mais ne devrait pas ) avoir une sématique significativement différente dans le contexte d'un indice de boucle, et cela pourrait (mais ne devrait pas) affecter le comportement de la boucle décrite.
aussi, dans c++
il est généralement plus sûr d'utiliser la forme de pré-incrément ( ++i
) parce qu'elle est plus facilement optimisée. (Scott Langham me battre pour cette friandise . Vous maudissent, Scott)
je ne sais pas pour les autres langues, mais en Java ++i est un préfixe incrément , qui signifie: "augmenter je par 1 et ensuite utiliser la nouvelle valeur de i dans l'expression, dans lequel je réside, et i++ est un postfix incrément , qui signifie les suivantes: utiliser la valeur actuelle de je dans l'expression et puis l'augmenter par 1. Exemple:
public static void main(String [] args){
int a = 3;
int b = 5;
System.out.println(++a);
System.out.println(b++);
System.out.println(b);
} et la sortie est:
- 4
- 5
- 6
i++ ; ++i ; les deux sont similaires, car ils ne sont pas utilisés dans une expression.
class A {
public static void main (String []args) {
int j = 0 ;
int k = 0 ;
++j;
k++;
System.out.println(k+" "+j);
}}
prints out : 1 1