1

so this is what visual studio gives when auto completing a for loop. I have been told that ++i is more effecient than i++ as the pre increment does not require the comiler to create a temporary variable to store i. and that I should use ++i unless I actually require i++. is there any reason that visual studio does this as a default or am I just overthinking it?

for (size_t i = 0; i < length; i++)
{

}
Sai
  • 31
  • 1
  • 7
  • Does it do it for more complicated types like a `std::vector::iterator`? For an `int` both cases are the same so it doesn't matter: https://stackoverflow.com/questions/24886/is-there-a-performance-difference-between-i-and-i-in-c/24887#24887 – NathanOliver Apr 30 '20 at 17:21
  • 1
    For `int`, I expect compiler to generate same code as value of `i++` is not used. – Jarod42 Apr 30 '20 at 17:22
  • 2
    The answer to "why" is: "convention." and the fact that it doesn't matter typically once optimizations are done. For more see https://stackoverflow.com/questions/484462/difference-between-pre-increment-and-post-increment-in-a-loop – L. Scott Johnson Apr 30 '20 at 17:28

2 Answers2

4

Some of this answer is based on my experience rather than on any hard facts, so please take it with a grain of salt.

Reasons for i++ as the default loop incrementor

Postfix vs Prefix

The postfix incrementor i++ produces a temporary pre-incremented value that's passed 'upwards' in the expression, then variable i is subsequently incremented.

The prefix incrementor ++i does not produce a temporary object, but directly increments i and passes the incremented result to the expression.

Performance

Looking at two simple loops, one using i++, and the other ++i, let us examine the generated assembly

#include <stdio.h>

int main()
{ 
    for (int i = 0; i < 5; i++) {
     //        
   }

   for (int j = 0; j < 5; ++j) {
       //
   }


    return 0;
}

Generates the following assembly using GCC:

main:
        push    rbp
        mov     rbp, rsp
        mov     DWORD PTR [rbp-4], 0
.L3:
        cmp     DWORD PTR [rbp-4], 4
        jg      .L2
        add     DWORD PTR [rbp-4], 1
        jmp     .L3
.L2:
        mov     DWORD PTR [rbp-8], 0
.L5:
        cmp     DWORD PTR [rbp-8], 4
        jg      .L4
        add     DWORD PTR [rbp-8], 1
        jmp     .L5
.L4:
        mov     eax, 0
        pop     rbp
        ret

.L3 corresponds to the first loop, and .L5 corresponds to the second loop. The compiler optimizes away any differences in this case resulting in identical code, so no performance difference.

Appearance

Looking at the following three loops, which one appeals to you most aesthetically?

   for (int i = 0; i < 5; i++) {
     //        
   }

   for (int i = 0; i < 5; ++i) {
       //
   }

   for (int i = 0; i < 5; i+=1) {
       //
   }

For me i+=1 is right out, and ++i just feels sort of... backwards

Ergonomics

  • i++) - Your hand is already in the correct position to type ) after typing ++
  • ++i) - Requires moving from upper row to homerow and back

History

Older C programmers, and current C programmers who write systems level code make frequent use of i++ to allow for writing very compact code such as:

// print some char * s
while(*s)
    putc(*s++);

// strcpy from src to dest
while (*dest++=*src++);

Because of this i++ became the incrementor C programmers reach for first, eventually becoming a sort of standard in cases where ++i vs i++ have the same functionally.

Ace.C
  • 1,201
  • 12
  • 22
-1

Choosing ++i instead there would merely be a style choice.

There are no performance gains to be had in this context. That is a myth.

i++ is also more "conventional" for a simple loop over ints.

You are of course free to write your own loop in your own style!

Asteroids With Wings
  • 17,071
  • 2
  • 21
  • 35
  • 2
    There may be performance issues depending on the data type and if the data type has overloaded the increment operators. For integers, there is a performance difference, but compilers usually optimize it out. – Thomas Matthews Apr 30 '20 at 17:43
  • @ThomasMatthews could you give examples of the performance difference for overloads and for unoptimized integer code? – Bananach Sep 14 '22 at 22:02