Post-Increment and Pre-Increment Concept

Post-increment and Pre-increment concept?

All four answers so far are incorrect, in that they assert a specific order of events.

Believing that "urban legend" has led many a novice (and professional) astray, to wit, the endless stream of questions about Undefined Behavior in expressions.

So.

For the built-in C++ prefix operator,

++x

increments x and produces (as the expression's result) x as an lvalue, while

x++

increments x and produces (as the expression's result) the original value of x.

In particular, for x++ there is no no time ordering implied for the increment and production of original value of x. The compiler is free to emit machine code that produces the original value of x, e.g. it might be present in some register, and that delays the increment until the end of the expression (next sequence point).

Folks who incorrectly believe the increment must come first, and they are many, often conclude from that certain expressions must have well defined effect, when they actually have Undefined Behavior.

Pre increment vs Post increment in array

You hit the nail on the head. Your understanding is correct. The difference between pre and post increment expressions is just like it sounds. Pre-incrementation means the variable is incremented before the expression is set or evaluated. Post-incrementation means the expression is set or evaluated, and then the variable is altered. It's easy to think of it as a two step process.

b = x++;

is really:

b = x;
x++;

and

b = ++x;

is really:

x++;
b = x;

EDIT: The tricky part of the examples you provided (which probably threw you off) is that there's a huge difference between an array index, and its value.

i = ++a[1];

That means increment the value stored at a[1], and then set it to the variable i.

m = a[i++];

This one means set m to the value of a[i], then increment i. The difference between the two is a pretty big distinction and can get confusing at first.

Second EDIT: breakdown of the code

{ 
int a[5] = { 5, 1, 15, 20, 25 } ;
int i, j, k = 1, m ;
i = ++a[1] ;
j = a[1]++ ;
m = a[i++] ;
printf ( "\n%d %d %d", i, j, m ) ;
}

First:

i = ++a[1];

At this point we know a[1] = 1 (remember arrays are zero indexed). But we increment it first. Therefore i = 2.

j = a[1]++;

Remember we incremented a[1] before, so it is currently 2. We set j = 2, and THEN incremented it to 3. So j = 2 and now a[1] = 3.

m = a[i++];

We know i = 2. So we need to set m = a[2], and then increment i. At the end of this expression, m = 15, and i = 3.

In summary,

i = 3, j = 2, m = 15.

How do the post increment (i++) and pre increment (++i) operators work in Java?

Does this help?

a = 5;
i=++a + ++a + a++; =>
i=6 + 7 + 7; (a=8)

a = 5;
i=a++ + ++a + ++a; =>
i=5 + 7 + 8; (a=8)

The main point is that ++a increments the value and immediately returns it.

a++ also increments the value (in the background) but returns unchanged value of the variable - what looks like it is executed later.

Concept difference between pre and post increment operator for STL

The difference is they do not yield the same result, while this particular example will do the same regardless of the increment form used. The pre-increment form first increments the value, and then returns it; while the post-increment form increments the result but returns the value previous to incrementation. This is usually a no cost for fundamental types, but for things like iterators it requires creating a temporary value to hold the non-incremented value, in order to be later returned.

Efficiency of postincrement v.s. preincrement in C++ [duplicate]

pre-increment introduces a data dependency into your code -- the CPU must wait for the increment operation to be completed before its value can be used in the expression."

Is this true?

It is mostly true - although perhaps overly strict. Pre increment doesn't necessarily introduce a data dependency - but it can.

A trivial example for exposition:

a = b++ * 2;

Here, the increment can be executed in parallel with the multiplication. The operands of both the increment and the multiplication are immediately available and do not depend on the result of either operation.

Another example:

a = ++b * 2;

Here, the multiplication must be executed after the increment, because one of the operands of the multiplication depends on the result of the increment.

Of course, these statements do slightly different things, so the compiler might not always be able to transform the program from one form to the other while keeping the semantics the same - which is why using the post-increment might make a slight difference in performance.

A practical example, using a loop:

for(int i= 0; arr[i++];)
count++;

for(int i=-1; arr[++i];) // more typically: (int i=0; arr[i]; ++i;)
count++;

One might think that the latter is necessarily faster if they reason that "post-increment makes a copy" - which would have been very true in the case of non-fundamental types. However, due to the data dependency (and because int is a fundamental type with no overload function for increment operators), the former can theoretically be more efficient. Whether it actually is depends on the CPU architecture, and the ability of the optimizer.

For what it's worth - in a trivial program, on x86 arch, using g++ compiler with optimization enabled, the above loops had identical assembly output, so they are perfectly equivalent in that case.


Rules of thumb:

If the counter is a fundamental type and the result of increment is not used, then it makes no difference whether you use post/pre-increment.

If the counter is not a fundamental type and the result of the increment is not used and optimizations are disabled, then pre-increment may be more efficient. With optimizations enabled, there is usually no difference.

If the counter is a fundamental type and the result of increment is used, then post-increment can theoretically be marginally more efficient - in some CPU architecture - in some context - using some compiler.

If the counter is not a fundamental type and the result of the increment is used, then pre-increment is typically faster than post-increment. Also, see R Sahu's answer regarding this case.

Pre vs Post Increment

When exactly is that +1 getting added?

According to the standard:

The value computation of the ++ expression is sequenced before the modification of the operand object.

From a layman's point of view:

  1. Computation of counter is sequenced, which could be part of the entire RHS of the statement or just the term counter++.
  2. Computation of counter += 1 is sequenced before the next statement in the program is sequenced.

There are two things to keep in mind.

  1. The value of a term -- what it evaluates to in an expression.
  2. The side effects of the evaluation of the term.

In the case of counter++:

The value of the term is the value of counter before it is incremented.

The side effect of evaluation of the term is incrementing of the value of counter.

My pre increment is working fine but not the post increment

Your post-increment operator is returning reference to local object, which will be destroyed when function ends, the returned reference is always dangling and dereference on it leads to UB.

Post-increment operator is supposed to return-by-value, e.g.

ComplexNumber ComplexNumber::operator++(int x) // postincrement
{
ComplexNumber c = *this;
++(*this);
return c;
}

Is it still better to prefer pre-increment over post-increment?

Yes. It shouldn't matter for built-in types. For such types, the compiler can easily analyze the semantics and optimize them — if that doesn't change the behavior.

However, for class-type, it may (if not does) matter, because the semantic could be more complex in this case.

class X { /* code */ };

X x;

++x;
x++;

The last two calls could be entirely different and may perform different things, just like these calls:

x.decrement(); //may be same as ++x (cheating is legal in C++ world!)
x.increment(); //may be same as x++

So dont let yourself trapped for the syntactic sugar.

Combined preincrement and postincrement in C

Read up on Undefined behavior and sequence points.

This is a slightly different, yet similar example (thanks Zan):

2) Furthermore, the prior value shall be accessed only to determine the value to be stored.

C++ example:

std::printf("%d %d", i,++i); // invokes Undefined Behaviour because of Rule no 2


Related Topics



Leave a reply



Submit