Increment Operators

Hello, I know that for ++i it increments before evaluating and that for i++ it increments after evaluating. However, I want to know why both for-loops output the same numbers 0,1,2,3,4. Shouldn't the first for-loop output 1,2,3,4?

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
using namespace std;

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


Hi,
No, it shouldn't. The output is correct as it is. The update statement in a for loop does not happen until after all the inner statements have been executed. So for i = 0, it will check the condition (0 < 5), which is true, then go into the body and execute the statements there (cout << i << endl). Then it updates (++i). So whether it's pre/post increment, it does not make a difference in a for loop.
Cheers
In the context of a for loop, they are the same.
But if you are assigning to a variable WATCH OUT!
1
2
3
4
5
6
7
8
for (/* Evaluates only once -->*/					    int i = 0;
     /* Evaluates AFTER every loop iteration AFTER statement below -->*/    i < 5;
     /* Evaluates AFTER every loop iteration -->*/		            (i + 5 - 5 + 1)
    )                                                                       // Same as ++i
									    // Same as i++
    {
        cout << i << endl;
    }


1
2
3
4
// Using prefix
int i = 0;
int j = 0;
j = ++i; // j = 1 /* Evaluates i + 1, then assigns. */ 


1
2
3
4
//Using postfix
int i = 0;
int j = 0;
j = i++; // j = 0 /* Assigns, then evaluates i + 1. */ 
Last edited on
It seems there’s no more performance difference between pre and post increment operator with modern compilers.
Once it used to be said pre-increment operators were usually faster than post-increment operator. So, for example, if you were using things heavier than primitive types, like iterators, you’d better use the pre-increment operator. Edit: --> and that still holds true!!
But nowaday someone says compilers optimisation has overcome that issue:
https://stackoverflow.com/questions/24886/is-there-a-performance-difference-between-i-and-i-in-c


Edit: I've modified my post becouse it was patently wrong. See keskiverto correction below.
Last edited on
Just for fun - depends exactly where you put it in a for loop
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
using namespace std;

int main()
{
   for ( int i = 5; --i; ) {
       cout << i;
   }

   cout << endl;

   for ( int i = 5; i--; ) {
       cout << i;
   }
}

Hello Lithia,

Refer to what SasuKe said and consider this to see the difference between pre and post increment on a variable outside the for loop.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>

int main()
{
	int j{ 0 };

	for (int i = 0; i < 5; ++i)
	{
		std::cout << i << "  " << ++j << std::endl;
	}

	j = 0;

	for (int i = 0; i < 5; i++)
	{
		std::cout << i << "  " << j++ << std::endl;
	}

	return 0;
}


Hope this helps,

Andy
Enoizat wrote:
It seems there’s no more performance difference between pre and post increment operator with modern compilers.
Once it used to be said pre-increment operators were usually faster than post-increment operator. So, for example, if you were using things heavier than primitive types, like iterators, you’d better use the pre-increment operator.
But nowaday someone says compilers optimisation has overcome that issue:
https://stackoverflow.com/questions/24886/is-there-a-performance-difference-between-i-and-i-in-c

That link, that discussion, is about C where increment exists only for primitive types. Yes, compiler can optimize out unused code, for both C and C++. Increment of primitive type when returned value is not used is a trivial case.

"Heavier than primitive types" is a different situation. How much different? Depends on the type.

There were two decent statements:
Pre-increment will sometimes be faster but never slower.
So the question one should be asking is not which of these two operations is faster, it is which of these two operations expresses more accurately what you are trying to accomplish.

... which naturally leads to a debate about what expresses what.

However, the performance was not part of the OP question here.


The syntax* of for is
1
2
3
for ( init ; cond ; incr ) {
  body;
}

That is almost (but not quite) the same as this while loop:
1
2
3
4
5
init ;
while ( cond  ) {
  body;
  incr;
}

The incr is evaluated after the body.


*There is now also a range-based for-loop syntax:
1
2
3
for ( init : range ) {
  body;
}

that expresses
for each element in range, do body
keskiverto wrote:
That link, that discussion, is about C where increment exists only for primitive types.

Yes, and the funniest part is that I was searching for a link which effectively described the performance differences between pre and post increment operator in C++ :-)
When I’ve chanced upon this page
https://stackoverflow.com/questions/24901/is-there-a-performance-difference-between-i-and-i-in-c
I’ve followed the upmost link without realizing I was moving from C++ to C.
My bad, my bad, my bad. And thanks a lot for your correction. I’ve modified my previous post.
keskiverto wrote:
the performance was not part of the OP question here

It wasn’t, but the statement “there’s no difference between pre and post increment operator in a for loop” could be improved.
Not central to the discussion, but this may be of interest:
C++ optimisers are quite clever these days. For instance, with clang++ (which knows how to elide redundant new/delete pairs), all these functions generate identical code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
struct A
{
    A& operator++() { ++v ; return *this ; }

    A operator++(int) 
    { 
        auto temp = new A(*this) ; // needless, of course
        ++*this ; 
        auto prev = *temp ;
        delete temp ; 
        return prev ; 
    }

    int v = 0 ;
};

int foo( A a )
{
    int s = 0 ;
    for( int i = 0 ; i < 199 ; ++i ) { ++a ; s += a.v ; }
    return s ;
}

int bar( A a )
{
    int s = 0 ;
    for( int i = 0 ; i < 199 ; ++i ) { a++ ; a++ ; s += a.v -= 1 ; }
    return s ;
}

int baz( int i )
{
    int s = 0 ;
    for( int j = 0 ; j < 199 ; ++j ) { s += ++i ; }
    return s ;
}

int baz2( int i )
{
    int s = 0 ;
    for( int j = 0 ; j < 199 ; ++j ) { s += i++ + 1 ; }
    return s ;
}

https://godbolt.org/g/cjUcKZ
Topic archived. No new replies allowed.