why prefix increment is faster than postfix increment?

J

jrefactors

I heard people saying prefix increment is faster than postfix
incerement, but I don't know what's the difference. They both are
i = i+1.

i++
++i

Please advise. thanks!!
 
J

John Carson

I heard people saying prefix increment is faster than postfix
incerement, but I don't know what's the difference. They both are
i = i+1.

They are obviously not both the same. The prefix form returns the value of
the variable after the incrementation and the postfix form returns the value
of the variable before the incrementation.

For the postfix form, the simple way to implement it is for the compiler to
produce code that creates a temporary that stores the original value and
then to return this value. For a built-in type, this is a cheap operation.
For a class object, it may be an expensive operation.
 
C

Christian Bau

I heard people saying prefix increment is faster than postfix
incerement, but I don't know what's the difference. They both are
i = i+1.

i++
++i

Please advise. thanks!!

The C answer and the C++ answer for the built-in operators are: Whoever
makes that claim is not only clueless, but is also the type of dangerous
clueless person who thinks they have a clue. Don't take _any_ advice of
them. Ever.

I don't think you are interested in the C++ answer for operator
overloading yet.
 
K

Kaz Kylheku

I heard people saying prefix increment is faster than postfix
incerement, but I don't know what's the difference. They both are
i = i+1.

i++
++i

If you are throwing away the result, there is no semantic difference at
all, because the only difference between ++i and i++ is whether i or i
+ 1 is returned.

If you don't throw away the result, then they are different operators;
you can't substitute one without the other without making compensating
changes in the surrounding program! You then end up with two different
programs that you have to compare as such. If there is a performance
difference between those programs, it's a result of not just changing
the i++ to ++i, or vice versa, but also a consequence of those other
compensating changes, and how your particular compiler and machine
deals with everything as a whole.

Note that in C++ (this is cross-posted to comp.lang.c++), both forms of
the operator can be user-defined. If you are dealing with a choice
between two forms of the user-defined operator, and performance is
critical, you obviously have to take that into consideration!
 
G

Gordon Burditt

I heard people saying prefix increment is faster than postfix
incerement, but I don't know what's the difference. They both are

Any claim that X is faster than Y that doesn't specify a specific
compiler and platform is FALSE. Even if Y is "do X 1000000 times".

Gordon L. Burditt
 
G

Greg

I heard people saying prefix increment is faster than postfix
incerement, but I don't know what's the difference. They both are
i = i+1.

i++
++i

Please advise. thanks!!

Consider this program:

void PrintElement(const std::vector<int>::iterator& i)
{
std::cout << *i << " ";
}

int main()
{
std::vector<int> v;

v.push_back(1); v.push_back(2); v.push_back(3);

std::vector<int>::iterator i = v.begin();

while (i != v.end())
PrintElement( i++ );

while (i != v.begin())
PrintElement( --i );
}

Which PrintElement() call is like the more efficient one: the one with
the postincremented parameter (i++) or the pre-decremented (--i)
parameter? Or is there no reason to think that there would be a
difference?

In this case, it is likely that first PrintElement call with the
postfix incremented paramter has more overhead than the second, because
the compiler must increment the iterator i before it calls
PrintElement. But when the call to PrintElement is made, the compiler
must pass the value of i (or a reference to a temporary copy of i) that
i had before it was incremented. Therefore the compiler has little
choice but to make a copy of i before incrementing i, so that it has an
iterator with which it can call PrintElement.

The second PrintElement call applies a prefix operator to the paramter;
the compiler can therefore pass i directly to PrintElement, since its
incremented value is the appropriate value to pass to PrintElement.

Of course, the difference is not likely to be great, but there is
nonetheless a basis for expecting postfix operators to be less
efficient than prefix operators, especially when applied to parameters
in a function call.

Greg
 
M

Martin Ambuhl

Greg said:
Consider this program:

void PrintElement(const std::vector<int>::iterator& i)
{
std::cout << *i << " ";
}
[etc.]

When you respond to posts which are crossposted to <
and <try to give answers that are acceptable in
both. You have posted a bunch of compilation errors to
< There is no need to consider your code at all.
 
G

Greg

Gordon said:
Any claim that X is faster than Y that doesn't specify a specific
compiler and platform is FALSE. Even if Y is "do X 1000000 times".

Not necessarily. If one can show that Y performs every operation that X
performs, and then has to perform additional operations outside of that
set and that require a measurable amount of time to complete, then one
would have successfully proven that X is faster than Y. And in fact
that is the case here: the postincrement operator may have to perform
an additional copy operation that the prefix version does not have to
perform. Otherwise the amount of work required of each is the same.

Greg
 
M

Michael Mair

Greg said:
Not necessarily. If one can show that Y performs every operation that X
performs, and then has to perform additional operations outside of that
set and that require a measurable amount of time to complete, then one
would have successfully proven that X is faster than Y. And in fact
that is the case here: the postincrement operator may have to perform
an additional copy operation that the prefix version does not have to
perform. Otherwise the amount of work required of each is the same.

Nope. Maybe in source code but not necessarily in the generated code.
The optimisation may have a stage which looks for certain patterns;
it is very well possible that the seemingly slower code qualifies for
the optimisation but the "faster" code does not. This may be the
compiler's fault or yours, depending on the problem at hand.

So, you are right most of the time but not always. However, C++ coding
guidelines often bring the ++()/()++ including the caveats as an
example of "avoiding premature pessimization" and rightly so.


Cheers
Michael
 
G

Gordon Burditt

I heard people saying prefix increment is faster than postfix
Not necessarily. If one can show that Y performs every operation that X
performs, and then has to perform additional operations outside of that
set and that require a measurable amount of time to complete, then one
would have successfully proven that X is faster than Y.

Not unless you can prove that the compiler generates the code that
way, and in order to do that, you have to choose a specific compiler.
You cannot test *ALL* compilers, including ones written between
your test and publishing the results. And you can't prove, for
example, that the compiler doesn't add a time-wasting loop to X but
not to Y, without referring to a specific compiler.

There are some situations where doing more can be faster.
For example repeating this statement 1000000 times could be
faster than doing it 10 times:
unsigned int x;

x = x << 1;

since if the width of x is less than 1000000 bits, this results in
a constant independent of the original value of x, and the compiler
might realize this, but if the width of x is greater than 10, and it
must be, it has to shift x.
And in fact
that is the case here: the postincrement operator may have to perform
an additional copy operation that the prefix version does not have to
perform. Otherwise the amount of work required of each is the same.

You're assuming things about the underlying instruction set that
may not be true, and assuming that the compiler doesn't do a
poor job of generating code for one and a good job for the other.
The effect of a cache hit/miss can also do funny things to code
that looks like it should run in the same time as other code.

Gordon L. Burditt
 
C

Christian Bau

"Greg said:
Not necessarily. If one can show that Y performs every operation that X
performs, and then has to perform additional operations outside of that
set and that require a measurable amount of time to complete, then one
would have successfully proven that X is faster than Y.

One would have proven no such thing.

Consider this:

double x, y;
memcpy (&x, &y, sizeof (x) - 1);
memcpy (&x, &y, sizeof (x));

A good compiler will translate the second memcpy to a simple assignment
of a double variable, for example:

Load double y into register
Store register into double x.

In fact, if this is the only time the address of x and y is taken, it is
quite possible that x and y are still kept in floating-point registers,
in which case this is a very fast register-to-register assignment.

On the other hand, the first memcpy will have a much more difficult
implementation, even though it copies one byte less. Not only will it
produce much more code, on most current processors that code will
execute considerably slower.
 
J

Jack Klein

I heard people saying prefix increment is faster than postfix
incerement, but I don't know what's the difference. They both are
i = i+1.

What people are these? What are their credentials so that you, or we,
should place any confidence in their opinions?
i++
++i

Please advise. thanks!!

One possible item of advice would be for you to associate with
different people.
 
B

Branimir Maksimovic

Christian Bau said:
One would have proven no such thing.

Consider this:

double x, y;
memcpy (&x, &y, sizeof (x) - 1);
memcpy (&x, &y, sizeof (x));

A good compiler will translate the second memcpy to a simple assignment
of a double variable, for example:

Load double y into register
Store register into double x.

In fact, if this is the only time the address of x and y is taken, it is
quite possible that x and y are still kept in floating-point registers,
in which case this is a very fast register-to-register assignment.

On the other hand, the first memcpy will have a much more difficult
implementation, even though it copies one byte less. Not only will it
produce much more code, on most current processors that code will
execute considerably slower.

Nonsense. First one will probably generate hardware excpetion, and
second one will probably work. Then again first one would be much faster
as it is simple nop where sizeof(x) == 1 but second one would copy contents.

Greetings, Bane.
 
M

Michael Mair

Branimir said:
Nonsense. First one will probably generate hardware excpetion, and
second one will probably work. Then again first one would be much faster
as it is simple nop where sizeof(x) == 1 but second one would copy contents.

The second one is guaranteed to work and have the same effect
as x = y, the first may lead to a trap representation of x but
can also work.
Are you sure that you are aware of the semantics of memcpy()?


Cheers
Michael
 
J

John Carson

Jack Klein said:
What people are these? What are their credentials so that you, or we,
should place any confidence in their opinions?

Herb Sutter and Andrei Alexandrescu, C++ Coding Standards, p.50: "The prefix
form is semantically equivalent, just as much typing, and often slightly
more efficient by creating one less object. This is not premature
optimization; it is avoiding premature pessimization."
 
M

Michael Mair

John said:
Herb Sutter and Andrei Alexandrescu, C++ Coding Standards, p.50: "The
prefix form is semantically equivalent, just as much typing, and often
slightly more efficient by creating one less object. This is not
premature optimization; it is avoiding premature pessimization."

An excellent _C++_ book by well-renowned authors; however, you neglected
to quote the context: This applies if we are interested only in the
side effect and not at all in the value of the expression.

As this is crossposted to c.l.c and as there are no overloaded operators
in C, this is wrong in its generality.

<OT>In fact, on processors with postincrement/predecrement only and if
stuck with a poorly performing compiler, this may be even completely
wrong.</OT>


Cheers
Michael
 
B

Branimir Maksimovic

Michael said:
The second one is guaranteed to work and have the same effect
as x = y, the first may lead to a trap representation of x but
can also work.

In case that sizeof(x) == 1 , I agree.
Are you sure that you are aware of the semantics of memcpy()?

Well, I don't need to, cause I don't use memcpy to assign variables.

Greetings, Bane.
 
J

John Carson

Michael Mair said:
An excellent _C++_ book by well-renowned authors; however, you
neglected to quote the context: This applies if we are interested
only in the side effect and not at all in the value of the expression.

You mean the original value of the expression. I took that to be understood.
As this is crossposted to c.l.c and as there are no overloaded
operators in C, this is wrong in its generality.

It is clear that its main significance is for C++. Whether it is completely
irrelevant for C I don't know. I would have imagined that i++ could easily
require an additional temporary even when i is an int. But the exact
efficiency consequences of this or some alternative with built-in types
requires a knowledge of compilers/processors that I don't have.
 
C

Christian Bau

"Branimir Maksimovic said:
Nonsense. First one will probably generate hardware excpetion, and
second one will probably work. Then again first one would be much faster
as it is simple nop where sizeof(x) == 1 but second one would copy contents.

I wish you a successful career. Maybe you should learn a bit about
programming, that might help.
 

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

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top