Qt/C++ - Tutorial 079. foreach vs range-based for in C++11?

Qt, foreach, for

Qt has its own keyword foreach to iterate through the elements of the containers. This keyword was introduced before the C++11 standard and is a macro. At this point in the C++11 standard, there are range-based for loops that perform the same functionality as foreach .

But in both cases there are nuances. Let's figure it out.

To which objects can be applied

foreach and range-based for work with containers that have an iterator. In this case there are no differences. They can only be applied to objects with an iterator.

Using, program code

Let's look at the program code. Suppose we have a container

QList<QString> strings;

And we want to do something with the elements of this container, then the record for foreach will look like this

foreach (QString& str, strings)
{
    // ToDo something
}

and for range-based for the record will be the next

for (QString& str : strings)
{
    // ToDo something
}

Preprocessor

The keyword foreach is a macro, which in the end will be equivalent to this record

for (QList<QString>::iterator it = strings.begin(); it != strings.end(); ++it) 
{
    QString &str = *it;
    // ваш код
}

But since this is a macro, we get an overhead by compilation time for processing the files by the preprocessor, which will deploy all these macros to the working code.

Speed of work

foreach runs slower range-based for loops because it performs a pre-copy of the container, as described in the Qt documentation. From the copying follows the following nuance, that if during the foreach operation you do something with the container, then this will not have an effect on the elements in the loop. In this case, implicit copying is carried out also when you do not modify the elements of the container.

This code behavior can be quite costly for STL containers, which are expensive to copy. Therefore, for this reason, it's better to use range-based for loops from the C++11 standard.

Disadvantages of range-based for

If you read the Qt documentation, you can find that they recommend still using foreach for Qt containers, and for all others (STL, Boost, etc.) use range-based for loops. This is motivated by the fact that a container with shared data during the operation of a range-based for loop can be detached from these shared data and not returned to its original state after the actions are performed, as a result of which data corruption can occur.

One such implicitly shared class is QPen, which uses deep copying when detach.

void QPen::setStyle(Qt::PenStyle style)
{
    detach();           // detach from common data
    d->style = style;   // set the style member
}

void QPen::detach()
{
    if (d->ref != 1) {
        ...             // perform a deep copy
    }
}

Conclusion

In my practice, I did not encounter such problems when using range-based for loops for Qt containers, I think, perhaps this is due to the fact that you did not have to often use such loops for containers with QPen objects or other Qt classes requiring separation from shared data.

In fact, recently the use of STL containers seems to me more convenient than the Qt containers in connection with the use of functors (lambd) for searching (std:; find, std :: find_if algorithms, etc.) of specific objects in the container, instead of the usual cycle with a condition in it.

I also adhere to the point of view that it is better to use language constructs instead of MACROS. Just need to consider that there may be problems, due to the peculiarities of containers and other Qt classes.

And the final solution for using foreach vs range-based for is left to your opinion.

We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.
Support the author Donate

Comments

Only authorized users can post comments.
Please, Log in or Sign up
TT
June 13, 2019, 7:01 p.m.
Taimoor Tanweer

C++ - Test 001. The first program and data types

  • Result:66points,
  • Rating points-1
TT
June 13, 2019, 6:51 p.m.
Taimoor Tanweer

C++ - Test 002. Constants

  • Result:75points,
  • Rating points2
ВМ
June 13, 2019, 12:30 p.m.
Ваня Мороз

C++ - Test 001. The first program and data types

  • Result:100points,
  • Rating points10
Last comments
i
June 17, 2019, 6:10 a.m.
ingenfly

Только по осям xAxis2, уAxis2 значения начинаются с 0. Почему-то xAxis2 и xAxis не синхронизированы по данным. Ну и QCustomPlot последний.
June 16, 2019, 8:21 p.m.
Евгений Легоцкой

Добрый день. Ну точно также добавляете ту же самую информацию на ось xAxis2, только добавляете другое форматирование customPlot->xAxis2->setDateTimeFormat("hh:mm"); если я ...
EF
June 14, 2019, 1:56 p.m.
Egor Fomin

Спасибо за ваш ответ, у меня получилось реализовать это. Тем не менее появилась другая проблема, поэтому опять надеюсь на вашу помощь. Скажем, я уже выставил точки и они соеденены. Когда я нач...
d
June 13, 2019, 2:47 p.m.
damix

Можно классу, который описывает точку, добавить сигнал, который подавать (emit), когда точка перемещается (переопределить mouseMoveEvent или mouseReleaseEvent). Так вот эти сигналы у каждой из...
i
June 13, 2019, 2:09 p.m.
ingenfly

Здравствайте! Подскажите, пожалуйста: customPlot->xAxis2->setTickLabels(true); //Здесь включается отображение данных на оси xAxis2. а можно как-то продублировать информацию cus...
Now discuss on the forum
June 20, 2019, 9:30 a.m.
IscanderChe

Вернулся к этой задачке только-только, поэтому и не ответил ничего раньше.Как переопределить mouseReleaseEvent(QMouseEvent* event) у QTableView, если QTableView задан в ui? Или задавать QTabl...
I
June 19, 2019, 1:41 p.m.
Intruder

Всем добрый день. При разборе XML файла наткнулся на тег вот такого плана: <TagName attribute1="value1" attribute2="value2" /> При попытке проверить на наличие такого элеме...
June 19, 2019, 12:55 p.m.
Михаиллл

Скажите пожалуйста, как его в таком случае перемещать и удалять?
June 18, 2019, 7:50 p.m.
Дмитрий

Большое спасибо! SDK заработал.К сожалению удалось продвинутся только на один шаг. При сборке чистого проекта NDK выдаёт следующие ошибки C:\Android\ndk-bundle/toolchains/arm-linux-andr...
June 18, 2019, 4:59 p.m.
Михаиллл

Добрый день.В этом учебнике представлен код INSTALLED_APPS = ( ... 'rest_framework', 'snippets.apps.SnippetsConfig',) На строчке 'snippets.apps.SnippetsConf...
Looking for a Job?
25,000.00 руб. - 30,000.00 руб.
Разработчик Qt/C++
Barnaul, Altai Krai, Russia

For registered users on the site there is a minimum amount of advertising

EVILEG
About
Services
Join us
© EVILEG 2015-2019
Recommend hosting TIMEWEB