'for' loop vs Qt's 'foreach' in C++

100,138

Solution 1

It really doesn't matter in most cases.

The large number of questions on StackOverflow regarding whether this method or that method is faster, belie the fact that, in the vast majority of cases, code spends most of its time sitting around waiting for users to do something.

If you are really concerned, profile it for yourself and act on what you find.

But I think you'll most likely find that only in the most intense data-processing-heavy work does this question matter. The difference may well be only a couple of seconds and even then, only when processing huge numbers of elements.

Get your code working first. Then get it working fast (and only if you find an actual performance issue).

Time spent optimising before you've finished the functionality and can properly profile, is mostly wasted time.

Solution 2

First off, I'd just like to say I agree with Pax, and that the speed probably doesn't enter into it. foreach wins hands down based on readability, and that's enough in 98% of cases.

But of course the Qt guys have looked into it and actually done some profiling: http://blog.qt.io/blog/2009/01/23/iterating-efficiently/

The main lesson to take away from that is: use const references in read only loops as it avoids the creation of temporary instances. It also make the purpose of the loop more explicit, regardless of the looping method you use.

Solution 3

It really doesn't matter. Odds are if your program is slow, this isn't the problem. However, it should be noted that you aren't make a completely equal comparison. Qt's foreach is more similar to this (this example will use QList<QString>):

for(QList<QString>::iterator it = Con.begin(); it != Con.end(); ++it) {
    QString &str = *it;
    // your code here
}

The macro is able to do this by using some compiler extensions (like GCC's __typeof__) to get the type of the container passed. Also imagine that boost's BOOST_FOREACH is very similar in concept.

The reason why your example isn't fair is that your non-Qt version is adding extra work.

You are indexing instead of really iterating. If you are using a type with non-contiguous allocation (I suspect this might be the case with QList<>), then indexing will be more expensive since the code has to calculate "where" the n-th item is.

That being said. It still doesn't matter. The timing difference between those two pieces of code will be negligible if existent at all. Don't waste your time worrying about it. Write whichever you find more clear and understandable.

EDIT: As a bonus, currently I strongly favor the C++11 version of container iteration, it is clean, concise and simple:

for(QString &s : Con) {
    // you code here
}

Solution 4

Since Qt 5.7 the foreach macro is deprecated, Qt encourages you to use the C++11 for instead.
http://doc.qt.io/qt-5/qtglobal.html#foreach

(more details about the difference here : https://www.kdab.com/goodbye-q_foreach/)

Solution 5

First, I completely agree with the answer that "it doesn't matter". Pick the cleanest solution, and optimize if it becomes a problem.

But another way to look at it is that often, the fastest solution is the one that describes your intent most accurately. In this case, QT's foreach says that you'd like to apply some action for each element in the container.

A plain for loop say that you'd like a counter i. You want to repeatedly add one to this value i, and as long as it is less than the number of elements in the container, you would like to perform some action.

In other words, the plain for loop overspecifies the problem. It adds a lot of requirements that aren't actually part of what you're trying to do. You don't care about the loop counter. But as soon as you write a for loop, it has to be there.

On the other hand, the QT people have made no additional promises that may affect performance. They simply guarantee to iterate through the container and apply an action to each.

In other words, often the cleanest and most elegant solution is also the fastest.

Share:
100,138
Ajay
Author by

Ajay

Software engineer

Updated on July 09, 2022

Comments

  • Ajay
    Ajay almost 2 years

    Which is better (or faster), a C++ for loop or the foreach operator provided by Qt? For example, the following condition

    QList<QString> listofstrings;
    

    Which is better?

    foreach(QString str, listofstrings)
    {
        //code
    }
    

    or

    int count = listofstrings.count();
    QString str = QString();
    for(int i=0;i<count;i++)
    {
        str = listofstrings.at(i);
        //Code
    }
    
  • JaredPar
    JaredPar about 15 years
    The number passed the joke stage long ago. We should write an answer bot that looks for "which is faster" and auto-replies: profile it
  • paxdiablo
    paxdiablo about 15 years
    See stackoverflow.com/questions/771092/… : let's see if it survives :-)
  • Michael Burr
    Michael Burr about 15 years
    Not that it really applies so much to the simple example, but what I like to say is, "Incorrect code is as unoptimized as you can get".
  • paxdiablo
    paxdiablo about 15 years
    Ooh, that's a good one, @MB, I'll add that to my list of mantras.
  • JaredPar
    JaredPar about 15 years
    @Michael that went onto my list as well.
  • David Thornley
    David Thornley about 15 years
    Most code in a program is only executed a limited number of times, and humans are bad at predicting which code (and humans who think they're good at it are also bad at it). Micro-optimizing code that isn't executed much is completely pointless. I'd never micro-optimize without knowing there as a performance issue, or without profiling the code.
  • Donal Fellows
    Donal Fellows almost 14 years
    @paxdiablo: “mostly wasted”? Damn close to all. (Very occasionally you know early on that a particular code path is going to be hot and can take special care with it, but it's ever so rare.)
  • PeterK
    PeterK almost 14 years
    @JaredPar: a bot seems a bit over the top, but a suggestion when creating the question would be indeed nice. We have the "seems subjective - probably will be closed" one, adding a few more should not be a problem.
  • Wim Leers
    Wim Leers about 13 years
    IMO, STL is not more "standard" than Qt. STL-style code is often extremely ugly. If you have to integrate with non-Qt C++ apps/libs, then it may be worthwhile. If you're just building a Qt app, using STL functions doesn't help you at all, instead, you'll be typecasting all the time.
  • Jeff Allen
    Jeff Allen almost 13 years
    There are cases where code size matters (space-constrained embedded devices, inner loops which must not be bigger than a cache line, etc) and in those cases foreach is a poor choice. A colleague just demonstrated that changing a foreach to a C-style for with an integer counter variable reduced the function in question by 250 bytes (take a look at the expansion of Qt's foreach to see why).
  • Tim Hoffmann
    Tim Hoffmann about 8 years
    Your statement concerning at() vs operator[] performance is not correct for Qt. Both do or do not perform bounds checking depending on compilation options. Exceptions are not used in Qt. In contrast, the documentation says "at() can be faster than operator[](), because it never causes a deep copy to occur."
  • scigor
    scigor over 7 years
    While this answer would be sufficient as a side comment, it does not answer the question. Scrolling down to the other answers you will actually find an answer and not a thousand times repeated discussion about when people should care about performance.
  • paxdiablo
    paxdiablo over 7 years
    @inf.ig.sh, it appeared to answer it well enough for the OP :-) I treat this sort of question similar to things like "how do I use bubblesort to sort a billion items?" or "how do I write an operating system in OOCOBOL?" Sometimes the answer really is "don't do that".
  • scigor
    scigor over 7 years
    @paxdiablo I strongly disagree. The answer you have given is "If you're really concerned, profile it for yourself.". Just because you got lucky and the OP did not get the code working first and was doing premature optimization does not mean that its a good answer. You answer would have been really great if you would have actually answered the question like several people below have and THEN added your comment. Just to say test it for yourself if you really need to is not an answer.
  • paxdiablo
    paxdiablo over 7 years
    @inf.ig.sh, you seem to have misunderstood the crux of the answer. The suggestion for the OP to profile it themselves was if they were really interested. However, the answer was that they shouldn't do this because the difference was almost certainly going to turn out to be irrelevant in the scheme of things (as evidenced by the excellent links provided by other answers). That was my answer. If you think it's unhelpful with it, that's what SO votes are for, I suggest you use them rather than trying to convince me. If enough people think as you do, it will have an effect.
  • scigor
    scigor over 7 years
    @paxdiablo I did use the votes. SO suggest to add an explanatory comment in case of a downvote. That's exactly what i did.
  • Dalton
    Dalton over 7 years
    I work at a market. A big one. A big one that sells millions of products in one month. And when I need to generate a report of that to the government, it makes a looooot of difference. Using QT's foreach, the report took 4 hours. Simply trading it for normal fors changed the speed to 15 min. So depending on your application, the difference is absurd.
  • Gerhard Burger
    Gerhard Burger over 4 years
    Please also add this as a comment to the question, more people need to see this!
  • Cem Polat
    Cem Polat over 2 years
    I believe that in rare cases a common answer can be given to the "which is faster" question for comparing the performance of functions or code snippets. In many cases the compiler(MSVC, gcc ), the platform(windows, mac, linux), the framework with libraries (boost, qt, opencv, libmkl ...etc) as well as the versions of those affect the comparisons so that an advised alternative may not fit for every one. It is nice to work in your own environment and make your own comparisons either with the profiler or simply measuring the elapsed time on multiple iterations(benchmarking).