basic for loop question

P

pauldepstein

Is there any difference between

for(int i = 0; some condition; i++)
{....}

and

for(int i = 0; some condition; ++i) ?
{....}

It seems not, by some experimenting, but I thought it was worth
checking since j++ and ++j usually mean different things in the
language ++c .

Thanks a lot,

Paul Epstein
 
A

Alf P. Steinbach

* (e-mail address removed):
Is there any difference between

for(int i = 0; some condition; i++)
{....}

and

for(int i = 0; some condition; ++i) ?
{....}

Technically no.

For forming habit of writing only what you mean, not requesting
additional needless operations (i.e. formong the habit of writing ++i
instead of i++), yes there is a difference.

This difference can be important when "i" is not a simple integer,
because i++ then generally has to make a copy.


Cheers, & hth.,

- Alf
 
M

Mateusz Loskot

Is there any difference between

for(int i = 0; some condition; i++)
{....}

and

for(int i = 0; some condition; ++i) ?
{....}

It seems not, by some experimenting, but I thought it was worth
checking since j++ and ++j usually mean different things in the
language ++c .

You mean difference in...performance, semantic,...?

Semantically, there is a difference because in the first case
temporary object is created.
There may or may not be difference in speed and performance. it depends
on C++ implementation you use, optimization, etc.

Cheers
 
K

keith

You mean difference in...performance, semantic,...?

Semantically, there is a difference because in the first case
temporary object is created.
There may or may not be difference in speed and performance. it depends
on C++ implementation you use, optimization, etc.

Generally speaking (and the FAQ book from Cline et al concurs:
Q23.08), one should use the prefix increment if the previous value of
the operand is discarded, as in the example above. The rationale is
that the postfix operator needs to make a copy of the operand,
increment the operand, then return the value of the copy; the prefix
operator merely needs to increment the operand and return its value.
 
L

Lionel B

Generally speaking (and the FAQ book from Cline et al concurs: Q23.08),
one should use the prefix increment if the previous value of the operand
is discarded, as in the example above. The rationale is that the
postfix operator needs to make a copy of the operand, increment the
operand, then return the value of the copy; the prefix operator merely
needs to increment the operand and return its value.

Out of interest, does the standard mandate that the postfix version is
*required* to make a copy? Obviously it's not going to make any
difference for an int (and I'd expect an optimising compiler to generate
identical code here), but when incrementing an object with a non-trivial
copy constructor it potentially could make a difference.
 
K

keith

Out of interest, does the standard mandate that the postfix version is
*required* to make a copy? Obviously it's not going to make any
difference for an int (and I'd expect an optimising compiler to generate
identical code here), but when incrementing an object with a non-trivial
copy constructor it potentially could make a difference.

I doubt the standard has anything to say on the matter, but how else
would you increment the operand (whatever that might mean for the
object concerned), _and_then_ return the previous value?
 
J

Joe Greer

Lionel B said:
Out of interest, does the standard mandate that the postfix version is
*required* to make a copy? Obviously it's not going to make any
difference for an int (and I'd expect an optimising compiler to generate
identical code here), but when incrementing an object with a non-trivial
copy constructor it potentially could make a difference.

The way I look at it is that ++i and i++ take the same number of keystrokes
to type and ++i better indicates what I mean (increment i and use that
value). That it has the side benefit of being more efficient without
relying on QOI is just a side benefit. In the case of user defined objects
with overloaded operator++, I am not sure how you could do it without
making a copy, but even if you could I don't think I would like to rely on
QOI to make that decision.

joe
 
J

James Kanze

Is there any difference between
for(int i = 0; some condition; i++)
{....}

for(int i = 0; some condition; ++i) ?
{....}

Yes. One is what other people on the project are doing in
similar cases. The other is not.
It seems not, by some experimenting, but I thought it was
worth checking since j++ and ++j usually mean different things
in the language ++c .

The difference is in the returned value. In this case, the
returned value is being ignored.

There have been claims (and still are, by people who prefer
speculation to measurement) that the prefix version will be
faster for user defined types, like iterators. For this reason,
on a green fields project, it is probably simpler to choose
prefix notation, and avoid the arguments. If there is any
existing code, however, just use whatever it uses, and don't
worry about it.
 
L

Lionel B

The way I look at it is that ++i and i++ take the same number of
keystrokes to type and ++i better indicates what I mean (increment i and
use that value).

I don't dispute that. I use prefix incrementation myself for simple loop
counters, or generally when the semantics doesn't require postfix
incrementation. However, that was not the point of my post.
That it has the side benefit of being more efficient

I imagine it would be equally efficient with basic optimisation... *if*
the compiler is allowed *not* to copy the object when it can establish
that the return value is not used.
without relying on QOI is just a side benefit.

I'm sorry, I have no idea what QOI means.
In the case of user
defined objects with overloaded operator++, I am not sure how you could
do it without making a copy,

Nor do I, but again, my query was kind of the converse of that: if you
use postfix increment in a situation where, say, you don't use the return
value, then can you make any assumptions about whether copying takes
place or not? (I guess the answer is probably "no you may not"...).
 
L

Lionel B

I doubt the standard has anything to say on the matter, but how else
would you increment the operand (whatever that might mean for the object
concerned), _and_then_ return the previous value?

Sorry, I obviously didn't express myself very well... the situation I had
in mind is where the return value of postfix increment is *discarded*.
Then, is the compiler allowed *not* to make a copy of the object?
 
J

Joe Greer

Lionel B said:
I'm sorry, I have no idea what QOI means.

Sorry, that would be quality of implementation. In other words, just
because an implementation can make an optimization, doesn't mean it will.
Nor do I, but again, my query was kind of the converse of that: if you
use postfix increment in a situation where, say, you don't use the
return value, then can you make any assumptions about whether copying
takes place or not? (I guess the answer is probably "no you may
not"...).

Yep, you can't really make any assumptions about it.

joe
 
E

Erik Wikström

Sorry, I obviously didn't express myself very well... the situation I had
in mind is where the return value of postfix increment is *discarded*.
Then, is the compiler allowed *not* to make a copy of the object?

There is something called the "as if" rule (section 1.9 of the standard)
which basically says that as long as the observable behaviour of the
program during execution is the same as if things were done as described
in the standard then the program is conforming. So if you do not try to
make any use of the returned value then the compiler should be free to
do nothing except increment the value.

For an integer this should be simple but for user defined types the
compiler might have some trouble to decide how much of the code is
needed an what it can safely skip, which is why it is generally
recommended to use the prefix version.
 
E

Erik Wikström

I don't dispute that. I use prefix incrementation myself for simple loop
counters, or generally when the semantics doesn't require postfix
incrementation. However, that was not the point of my post.


I imagine it would be equally efficient with basic optimisation... *if*
the compiler is allowed *not* to copy the object when it can establish
that the return value is not used.

And provided that it is as simple as just neglecting to create a copy,
not that I can come up with an example but one could imagine that there
were some other complications which makes it difficult for the compiler
to skip the part of the code which creates the copy.
I'm sorry, I have no idea what QOI means.

Quality Of Implementation.
Nor do I, but again, my query was kind of the converse of that: if you
use postfix increment in a situation where, say, you don't use the return
value, then can you make any assumptions about whether copying takes
place or not? (I guess the answer is probably "no you may not"...).

Generally you can not make such an assumption, no. With a good compiler
and with no weird implementations of the ++ operator you might, but
unless you check the code generated for each usage you can never be sure.
 
J

James Kanze

On 2008-01-25 17:27, Lionel B wrote:
Generally you can not make such an assumption, no. With a good
compiler and with no weird implementations of the ++ operator
you might, but unless you check the code generated for each
usage you can never be sure.

Use the copy in any way. Use the copy in the postfix increment
operator, for example, something like:

T
operator++( T& obj, int )
{
T result( obj ) ;
operator++( obj ) ;
result.dump( std::cout ) ; // outputs internal state...
return result ;
}

It's easy to invent cases where postfix would be slower. The
fact is that they don't occur in practice. To begin with, the
copy must be fast and efficient to begin with, since the STL
copies iterators like crazy anyway. And the things you do to
make it fast and efficient (e.g. like keeping the internal state
simple, and making the copy constructor inline) help the
compiler in optimizing it.

I've posted this several times before, but I carefully
benchmarked loops with prefix and postfix increment, for all of
the standard iterators, using g++, and there was no difference.

One thing that did make a difference (although not a large one)
was moving the call to end() out of the loop:

for ( Iter i = c.begin(), e = c.end() ; i != e ; i ++ ) {
}

turns out to be measurably faster than:

for ( Iter i = c.begin() ; i != c.end() ; ++ i ) {
}

in fact. But the difference is always small enough that it
would be foolish and a waste of time to even think about it
(until the profiler says otherwise, of course).
 
R

Rolf Magnus

Joe said:
The way I look at it is that ++i and i++ take the same number of
keystrokes to type and ++i better indicates what I mean (increment i and
use that value).

You don't use the value (at least not in the example the OP posted). You
discard it. So in that regard, both variants are the same. With ++i, you
discard the new value, with i++, you discard the old one.
 
R

Rolf Magnus

James said:
Yes. One is what other people on the project are doing in
similar cases. The other is not.


The difference is in the returned value. In this case, the
returned value is being ignored.

There have been claims (and still are, by people who prefer
speculation to measurement) that the prefix version will be
faster for user defined types, like iterators. For this reason,
on a green fields project, it is probably simpler to choose
prefix notation, and avoid the arguments. If there is any
existing code, however, just use whatever it uses, and don't
worry about it.

Considering that - except for the potential difference in execution time -
there is no difference, why use the postfix version? If I definitely don't
gain anything from one solution, but might (even if chances are slim) gain
something from the other, then I use of course that one.
 
J

James Kanze

James Kanze wrote:

[...]
Considering that - except for the potential difference in
execution time - there is no difference, why use the postfix
version?

Typically, because it is the established coding convention where
you're working.
If I definitely don't gain anything from one solution, but
might (even if chances are slim) gain something from the
other, then I use of course that one.

Supposing all other things equal. They usually aren't. If your
shop has the established tradition of using the postfix op
(frequent, if for no other reason that that's what K&R did),
that's a very strong reason for using postfix---it requires (or
should require) significant motivation to change. And that
significant motivation isn't there.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,183
Messages
2,570,967
Members
47,518
Latest member
RomanGratt

Latest Threads

Top