Difference between pre-increment and post-increment in a loop?

后端 未结 22 1737
暗喜
暗喜 2020-11-21 23:41

Is there a difference in ++i and i++ in a for loop? Is it simply a syntax thing?

相关标签:
22条回答
  • 2020-11-22 00:22

    There is more to ++i and i++ than loops and performance differences. ++i returns a l-value and i++ returns an r-value. Based on this, there are many things you can do to ( ++i ) but not to ( 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;
    }
    
    0 讨论(0)
  • 2020-11-22 00:24

    Yes, there is. The difference is in the return value. The return value of "++i" will be the value after incrementing i. The return of "i++" will be the value before incrementing. This means that code that looks like the following:

    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.
    

    Therefore, a would be 2, and b and c would each be 1.

    I could rewrite the code like this:

    int a = 0; 
    
    // ++a;
    a = a + 1; // incrementing first.
    b = a; // setting second. 
    
    // a++;
    c = a; // setting first. 
    a = a + 1; // incrementing second. 
    
    0 讨论(0)
  • 2020-11-22 00:24

    In javascript due to the following i++ may be better to use:

    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.
    

    While arrays (I think all) and some other functions and calls use 0 as a starting point you would have to set i to -1 to make the loop work with the array when using ++i.

    When using i++ the following value will use the increased value. You could say i++ is the way humans count, cause you can start with a 0.

    0 讨论(0)
  • 2020-11-22 00:24

    To understand what a FOR loop does

    enter image description here

    The image above shows that FOR can be converted to WHILE, as they eventually have totally the same assembly code (at least in gcc). So we can break down FOR into a couple of pieces, to undertand what it does.

    for (i = 0; i < 5; ++i) {
      DoSomethingA();
      DoSomethingB();
    }
    

    is equal to the WHILE version

    i = 0; //first argument (a statement) of for
    while (i < 5 /*second argument (a condition) of for*/) {
      DoSomethingA();
      DoSomethingB();
      ++i; //third argument (another statement) of for
    }
    

    It means that you can use FOR as a simple version of WHILE:

    1. The first argument of FOR (int i) is executed, outside, before the loop.

    2. The third argument of FOR (i++ or ++i) is executed, inside, in the last line of the loop.

    TL:DR: no matter whether i++ or ++i, we know that when they are standalone, they make no difference but +1 on themselves.

    In school, they usually teach the i++ way, but there are also lots of people prefer the ++i way due to several reasons.

    NOTE: In the past, i++ has very little impact on the performance, as it does not only plus one by itself, but also keeps the original value in the register. But for now, it makes no difference as the compiler makes the plus one part the same.

    0 讨论(0)
  • 2020-11-22 00:26

    One (++i) is preincrement, one (i++) is postincrement. The difference is in what value is immediately returned from the 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, entirely ignored the loop side of things. There's no actual difference in for loops when it's the 'step' portion (for(...; ...; )), but it can come into play in other cases.

    0 讨论(0)
  • 2020-11-22 00:26

    Here is a Java-Sample and the Byte-Code, post- and preIncrement show no difference in 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;
            }
        }
    }
    

    And now for the 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
    
    }
    
    0 讨论(0)
提交回复
热议问题