How ++c can be Faster than c++


In for-loops, people will tell you to always increment using ++c instead of c++. Why exactly is this? And will it affect your program in any way?

The observable difference between ++c and c++ is that the former evaluates to c+1, and the latter to c:

int main() {
    int c = 1;
    cout << ++c << endl;  // 2
    cout << c++ << endl;  // still 2
    cout << c << endl;  // 3
}

First of all, to get that question out of the way: This does not mean that the first alternative will increment c at the beginning of the iteration. Both alternatives increment c at the end of each iteration:

int main() {
    for (int c = 0; c < 1; c++) {
        cout << c << endl; // 0
    }
    for (int c = 0; c < 1; ++c) {
        cout << c << endl; // still 0
    }
}

So what then, is the point? Speed is.

Consider how the ++c operator would be implemented. No one will ever use the old value of c, so the implementer is free to increment c and then provide a reference to the freshly updated object. Now consider c++. Here, the implementer needs to provide a reference to the not-updated object, but still increment it. A common way to do this is to make an unmodified copy of c, increment the original c, and then return the copy. See the following example:

struct C {
    int _i;
    C(int i = 0) : _i(i){}

    C& operator++() {
        _i++;
        return *this;
    }

    C operator++(int) {
        C tmp(_i);
        _i++;
        return tmp;
    }
};

ostream& operator<< (ostream& os, const C& c) {
    os << c._i;
    return os;
}

int main () {
    C c;
    cout << c << endl; //0
    cout << c++ << endl; //0
    cout << ++c << endl; //2
}

As you can see, this introduces unnecessary overhead, especially for complex classes.

But what about built in types? For these, there will typically be no overhead using c++, but if you get into the habit of always using ++c, you won’t forget when you are incrementing more complex classes.

And as @tfheen points out, “[cases like the above example will be optimized away by] any compiler less than 30 years old.”, so this advice is probably not that relevant anymore. But now at least you know the reasoning when you see it.

C++0x highlights #0: Range Based For Loop


Herb Sutter has some good news, C++0x looks like it could end up as C++11! This is going to be a great update to the C++ language. Lots of advanced features, like closures, a new memory model, portable threading support etc., are coming, but I think the one that I miss most often is the really simple Range Based For Loop (especially combined with Type Inference).

The following for loop:

map<SomeClass, vector> someclass_strings_map;
for (map<SomeClass, vector>::const_iterator it = someclass_strings_map.begin();
    it != someclass_strings_map.end(); ++it) {
    do_something_with(it->second);
}

is one of the reasons the Python, Ruby (and Java since 1.5) people laugh at us. But next year, we will be able to do:

for (auto x : foo_strings_map) {
        do_something_with(x.second);
}

PS: while I was compiling this example, I remembered another tiny improvement, you can now do map<Foo, vector<string>>. Notice the missing space? C++ no longer confuses nested templates with the shift/stream operator. Currently, you need an extra space: map<Foo, vector<string> >

PPS: If do_something_with() is a simple function this could be done with a for_each and a lambda/closure, but that is another story.

If you enjoyed this post, you can subscribe to my blog, or follow me on Twitter.