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?

249
demandé sur Zesty 2009-01-27 20:53:19

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++) { }
195
répondu Chris S 2017-10-08 12:45:36

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.

195
répondu Scott Langham 2017-11-22 13:31:55

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.

76
répondu Jon B 2009-01-27 19:11:00

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é.

28
répondu Johannes Schaub - litb 2009-01-27 18:02:10

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.

24
répondu Vinzenz 2016-10-19 20:56:44

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++;
            }
        }
    }
}
15
répondu Joe Erickson 2009-01-27 18:22:47

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.

14
répondu Cody Brocious 2009-01-27 18:01:37

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

}
8
répondu Mirko Friedenhagen 2009-01-27 22:31:27

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.

6
répondu user3304868 2015-06-28 06:02:42

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. 
5
répondu David Morton 2009-01-27 20:47:25

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
4
répondu CMS 2009-01-27 17:58:16

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;
}
3
répondu Tanveer Badar 2009-01-27 19:32:39

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 .

3
répondu xaddict 2009-01-27 20:04:50

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.

3
répondu Mont Pierce 2016-10-17 02:20:17

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
1
répondu crashmstr 2017-05-23 12:17:55

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).

1
répondu Leonidas 2009-01-27 18:35:38

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 .

1
répondu Boubakr 2014-11-21 21:08:46

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 de i par 1 et, plus tard, d'évaluer les i ,
  • i++ signifie " évaluer i et, plus tard, la valeur d'incrément de i 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)
}
1
répondu Işık 2017-03-11 18:45:19

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)

-2
répondu dmckee 2017-05-23 12:10:11

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
-2
répondu Tano 2015-10-12 09:09:05

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
-3
répondu Java Main 2016-11-30 15:33:16