29

When iterating through a QList<T> with a foreach loop, in the tests I conducted the items are returned in the same order as they are with a standard for loop.

My question is, will the foreach always return items in numerical order by index like this, for containers that have natural ordering (like QList and QVector)? For example, are the following always equivalent?

QList<T> list;

for( int i=0; i<list.count(); ++i )
{ 
    // process items in numerical order by index
    // do something with "list[i]";
}

foreach( T item, list )
{ 
    // will items always be processed in numerical order by index?
    // do something with "item";
}
Freedom_Ben
  • 11,247
  • 10
  • 69
  • 89
  • You cant use [i] operator on list, but only in table (vectors ...) to have a random acces on memory. Moreover, try the c++11 foreac loop : (for(T& item : list) {/*some code */}). May be this can help – Krozark May 29 '13 at 23:12
  • @Krozark Nope, `operator[]` works just fine. See: http://qt-project.org/doc/qt-4.8/qlist.html#operator-5b-5d – Nikos C. May 29 '13 at 23:14
  • @NikosC. Ok, but not in STL. So for your problem, the most efficient is to use iterators using begin() and end() (i realy don't know what the foreach macro do ...) – Krozark May 29 '13 at 23:17

2 Answers2

34

The foreach macro (aka. Q_FOREACH) uses the begin() and end() iterator request methods of the container.

So if your container is a QList or QVector then your examples will always be equivalent. You can view the foreach source code here.

The foreach macro isn't great though, it makes a copy of the container - so only use on containers that support implicit-sharing. Use C++11 for( : ) {} loops if available, otherwise Boost has an equivalent that is superior.

cmannett85
  • 21,725
  • 8
  • 76
  • 119
  • Link is dead. Please avoid linking without giving the answer as well (or an extract). – David Zwart Dec 03 '19 at 09:45
  • @cmannett85, can you tell me how to loop QList using `for ( : ) { }` ? sorry for asking 8 years ago question – Denis Turgenev Jun 23 '21 at 02:32
  • @Freedom_Ben, can you tell me how to loop QList using for ( : ) { } ? – Denis Turgenev Jun 23 '21 at 02:33
  • @cmanett85, I've used thousands of foreach loop in my project, and I realized that moving to for (:){} can lead to a great performance upgrade after seeing your answer. please help me. I have snippet.h and copy all iterations from that file, and unfortunately it was foreach version. – Denis Turgenev Jun 23 '21 at 02:44
  • @DenisTurgenev https://en.cppreference.com/w/cpp/language/range-for and you won't see a 'great performance upgrade' because `QList` is a Qt container and therefore uses implicit sharing. – cmannett85 Jun 23 '21 at 07:17
  • thank you, @cmannett85, so for QList, foreach and for(:){} both don't make a copy of the container ?? – Denis Turgenev Jun 23 '21 at 09:11
  • yes, Qt says that "Since Qt 5.7, the use of this macro is discouraged. It will be removed in a future version of Qt. Please use C++11 range-for, possibly with qAsConst(), as needed." And maybe `for ( :) {}` seems to be a better practice. Just surprising, how compiler can detect container classes(even Qt Class). It's awesome – Denis Turgenev Jun 23 '21 at 09:16
  • How do I know if the container support implicit sharing? – KcFnMi Oct 06 '22 at 07:43
3

Based on the information found here, foreach is much slower than the first, suggesting that it is not equivalent.

Tarod
  • 6,732
  • 5
  • 44
  • 50
Krozark
  • 862
  • 9
  • 27
  • 4
    You are right, but you haven't understood why. In those tests the *first* `foreach` test was so much slower because of the creation of a `QString` shallow copy on each iteration, using a const ref of the actual container data made the times go back to roughly the same as the other tests because it bypassed the shallow copy. Conversely using a list of `ints` would have had the same effect. – cmannett85 May 30 '13 at 07:38