Skip to content
Link

Some Helpful Linux Commands

Some Helpful Linux Commands

Poignant Guide to Ruby

Here’s an informative and entertaining e-book guide to the Ruby programming language, available free of charge: http://mislav.uniqpath.com/poignant-guide/

Why is pre-increment preferred to post-increment in C++?

This came up in a code review recently.   C++ has two increment (“++”) operators that work similarly.  For a built-in type, like an int, they do the same thing  — increment the value of the variable by one.  They differ, though, in that the value of the resulting expression is the old value in the case of post increment, and the new value in the case of pre-increment.   For example:


int foo = 1, bar = 1;
int m = foo++;
int n = ++bar;

After this code is executed, foo, bar and n all have the value 2.  But the variable m has the value 1, because while the expression foo++ increments foo, the value of the expression is the old value of foo, prior to the increment.

If you think in terms of functions, each of the two operators has the same side effect of incrementing the integer. But the return values differ: one returns the value prior to the side effect and the other returns the value after.

Simple enough.   Of course in some cases you aren’t interested in the value of the expression, and are free to use either the pre or post-increment operator.  This is common in loops, for example:


for(int i = 0; i < LOOP_MAX; ++i) 
{
    // do something
}

Here we don’t care what the value of the ++i expression is, because we’re not using it. So which should you prefer?  For built-in types like int, it makes no difference at all.  I’ve heard it stated that in the case of post-increment that the compiler “has to save the old value in a temporary variable” or some such nonsense, and it isn’t true, as looking at the output of any compiler will show you.  Your compiler is not going to create a temporary variable that it isn’t going to use. In fact for ints, i++ and ++i will compile to a single machine instruction.

If there’s no difference for built-in types, then what about user-defined types (classes)? First of all, it’s impossible to make a general statement. If foo is an instance of the Foo class, the implementor may well have decided that foo++ should compute and return the value of pi to 10,000 places, whereas ++foo should connect to the IRS web site and file your tax forms electronically. The compiler doesn’t know or care what foo++ and ++foo do, and they don’t even have to do anything related.

On the other hand, if we assume that Foo‘s author has preserved the basic semantics for his user-defined type to parallel those of the built-in pre- and post-increment operations, the post-increment operator will be more expensive. This is certainly true for the STL iterator types, for example. The reason is that the post-increment will have do everything the pre-increment does to accomplish its side effect, and will have to create a copy of the old value as well in order to return it after the side effect takes place. The two will look something like this:


Foo &Foo::operator++() {
    // do something to increment the value
    return *this;
}

Foo &Foo::operator++(int dummy) 
{
    Foo temp(*this);
    // do something to increment the value
    return temp;
}

These are, in order, the pre- and post-increment operators for Foo, for which the ++foo and foo++ notations are syntactic sugar. (Note the dummy integer parameter to the post-increment operator. It’s unused, and required simply to give the post-increment version a different signature for overloading.) If you look at an iterator implementation in your favorite library, it will look something like this. In fact, the post-increment function may actually call the pre-increment operator to get its work done. Moral of the story: for classes, use pre-increment if performance is a concern and you aren’t going to look at the return value anyway.

Note that his all applies equally to the pre- and post-decrement operators (““) as well.

Follow

Get every new post delivered to your Inbox.