Click to See Complete Forum and Search --> : For Loop- Post increment, pre increment count


erankushmehta
April 25th, 2006, 05:00 AM
for (int i = 0; i<=12; i++)
cout << i << endl;

The code above and below gives the same output.
0
1
2
.
.
12
But i think it should start output from 1 for the code below.
for (int i = 0; i<=12; ++i)
cout << i << endl;

wildfrog
April 25th, 2006, 05:07 AM
But i think it should start output from 1 for the code below.

The for statement :

for ( init-expression ; cond-expression ; loop-expression )
statement
First the init-expression is executed once.The the cond-expression is evaluated before it continues to the statement. At the end the loop-expression is executed.

- petter

NMTop40
April 25th, 2006, 05:25 AM
The code is equivalent to:


int i=0;
while ( i <= 12 )
{
cout << i << endl;
++i;
}

Makes no difference if you do i++ or ++i. The latter is preferable as it is sometimes more efficient (eg looping with iterators that are not pointers) and never less efficient.

erankushmehta
April 25th, 2006, 06:10 AM
okay, fine but then it creates confusion about the concept of post increment & preincrement operator in general. When exactly does the value of post increment is updated if not immediately like pre increment operator (in general, not specifically here).This is quite mysterious for me.

wildfrog
April 25th, 2006, 06:24 AM
When exactly does the value of post increment is updated if not immediately like pre increment operator (in general, not specifically here).
Basically every expression evaluates to a value:

// this evaluates to the value of i
i;

// this also evaluates the original value of i (but at the same time i is incremented by one)
i++;

// this evaluates to the new value of i (after i is incremented by one)
++i;



// i is assigned to j before i is incremented
j = i++;

// i is first incremented, and then assigned to j
j = ++i;

- petter

philkr
April 25th, 2006, 06:42 AM
You can see the difference best if you see the operators as a function:

int PreIncrement(int a)
{
a = a + 1;
return a;
}

int PostIncrement(int a)
{
int temp = a; // This is the reason why it is slightly slower
a = a + 1;
return temp;
}

erankushmehta
April 25th, 2006, 07:58 AM
then for post increment, 13 should be printed...
First time, 0 is printed after intialisation and conditional comparison.
Then i++(i=i+1) evaluates to 0, compares with <=12, Prints 1(cout statement)
i++ evaluates to 1, compares with <=12, Prints 2
i++ evaluates to 2, compares with <=12, Prints 3
i++ evaluates to 3, compares with <=12, Prints 4
i++ evaluates to 4, compares with <=12, Prints 5
i++ evaluates to 5, compares with <=12, Prints 6
i++ evaluates to 6, compares with <=12, Prints 7
i++ evaluates to 7, compares with <=12, Prints 8
i++ evaluates to 8, compares with <=12, Prints 9
i++ evaluates to 9, compares with <=12, Prints 10
i++ evaluates to 10, compares with <=12, Prints 11
i++ evaluates to 11, compares with <=12, Prints 12
i++ evaluates to 12, compares with <=12, Prints 13(//Why this doesn't happen)

wildfrog
April 25th, 2006, 08:10 AM
then for post increment, 13 should be printed...
First time, 0 is printed after intialisation and conditional comparison.
Then i++(i=i+1) evaluates to 0, compares with <=12, Prints 1(cout statement)i++ evaluates to 12, compares with <=12, Prints 13(//Why this doesn't happen)The expression 'i++' (by itself) evaluates to 0 (and increase i to 1), but the cond-expression is a differenct expression and sees i as 1 (not 0).

- petter

erankushmehta
April 25th, 2006, 08:20 AM
That means for i++, if we cout we get original value but when we use it in an expression the updated or incremented value is used.Am i right if i use this generalisation?

wildfrog
April 25th, 2006, 08:29 AM
That means for i++, if we cout we get original value but when we use it in an expression the updated or incremented value is used.Am i right if i use this generalisation?
No. You'll always 'get' the original value when using i++. With ++i you 'get' the updated value.


// in this example i becomes 7 and j becomes 6 + 5 = 11
int i = 6;
int j = (i++) + 5;

// in this example i becomes 7 and j becomes (6+1) + 5 = 12
int i = 6;
int j = (++i) + 5;

- petter

dcjr84
April 25th, 2006, 11:32 AM
Some very good explanations here. They should help you out quite a bit.
Just my two cents here, the way I was taught when I learned C++.

When used by itself (i.e. not in an expression) it does not not matter
whether you use post or pre incrementation

I.e.

for ( int i=0; i <=12; i++)

Or..

for ( int i=0; i <=12; ++i )


Now pre-incrementation does reduce CPU cycles because it uses one
less instruction than post incrementation, but this will make little to no
difference in most programs that you write. At least while in the learning phase :)

SuperKoko
April 25th, 2006, 03:33 PM
Now pre-incrementation does reduce CPU cycles because it uses one
less instruction than post incrementation, but this will make little to no
difference in most programs that you write. At least while in the learning phase

One less instruction?
Not for builtin types.
For builtin types, there is no difference, as long as the yielded value is not used (at least for all common compiler, including Turbo C++ 1.0).

And, if the yielded value is used, such as in:
*p++ vs *++p, then the post-increment is likely to be a bit faster (not significantly) on modern CPU.

Because, instead of:

; pre-increment with space optimization
inc esi
mov eax,[esi] ; AGI stall (on pentium CPU) + dependency

; pre-increment with speed optimization
mov eax,[esi+1] ; four bytes of code are lost, but 1 or 2 CPU cycles gained.
inc esi

; post-increment with speed or space optimization
mov eax,[esi]
inc esi

Of course, that is more subtle than that, if other operations are combined, but *p++ is easier to optimize than *++p.

However, for iterators, ++p is very often MUCH faster than p++.

So, the rule is : Use ++p as often as you can, and p++ only if you need it (that is, almost never).

An example of judicious use of it++ is the removal of an item in a list (not an STL std::list) or similar container:

lst.erase(it++); // exception safe : Atomicity, Consistency and Isolation, even if iterator assignments can throw.
// However, it=lst.erase(it), is fine with STL containers since iterators copy-assignment operators can't throw.

dcjr84
April 25th, 2006, 09:11 PM
Thanks for the correction SuperKoko, I appreciate the post.
I was only trying to say that in general, it is really not going to make a noticeble difference in performance whether you use ++i or i++. Unless you have some specific reason for speed/efficiency optimization.

erankushmehta
April 27th, 2006, 12:58 AM
Thanks all for enlightening explanations. Just a final confirmation frm ur side:

i=0;
i++;
cout << i;
output will be 1.

i=0;
++i;
cout << i;
output will be 1.

is it okay.. :)

SuperKoko
April 27th, 2006, 04:32 AM
Thanks all for enlightening explanations. Just a final confirmation frm ur side:

i=0;
i++;
cout << i;
output will be 1.

i=0;
++i;
cout << i;
output will be 1.

is it okay.. :)
Yes!
That's okay!