Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Conflict in Qt Doc on the usage of foreach keyword and range-based for?



  • Hi there!
    I'm a newbie to Qt containers.

    https://doc.qt.io/qt-5/containers.html#the-foreach-keyword
    This page says If in doubt, prefer foreach for Qt containers, and range based for for STL ones.
    https://doc.qt.io/qt-5/qtglobal.html#foreach
    But this says Note: 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.
    This seems to be a conflict?

    If it's not, could you explain the typical usage of both?
    I've learned that range-based for might force a Qt container to detach, whereas foreach would not and Since foreach creates a copy of the container, using a non-const reference for the variable does not allow you to modify the original container. It only affects the copy, which is probably not what you want.
    But I'm still having this doubt.

    Thanks!


  • Moderators

    It will be removed in a future version of Qt

    There has actually been a decision made to cancel this removal. foreach is still available in Qt 6.

    This seems to be a conflict?

    On first sight yes, but in reality - no. C++ ranged for is recommended for Qt and STL containers, but if you are unsure how to use it properly - use foreach as it's safer and allows you to iterate even while the container is chaning.

    If it's not, could you explain the typical usage of both?

    foreach - I don't use it anymore. But in general, you can use it safely with all Qt containers. It will be efficient and safe. If you use it on STL containers, you will experience a performance hit (poor performance).

    ranged for - I use it for both STL and Qt containers. The only thing to remember is that Qt containers have to be const, like this:

    for (const auto &item : qAsConst(list)) {
    }
    

    The item can be mutable. But the list has to be const, otherwise the container will detach and do a deep copy.

    Other than that, ranged for is good for all container types, it's fast and compilers can optimize it well.

    I need to add one final hint, though: for small containers, it all does not matter much. Modern computers are so fast, that if you use for wrongly, the performance penalty will be in nanoseconds or miliseconds tops. Only for big containers (hundreds, thousands of items etc.) it becomes important to use the loop correctly.


  • Moderators

    It will be removed in a future version of Qt

    There has actually been a decision made to cancel this removal. foreach is still available in Qt 6.

    This seems to be a conflict?

    On first sight yes, but in reality - no. C++ ranged for is recommended for Qt and STL containers, but if you are unsure how to use it properly - use foreach as it's safer and allows you to iterate even while the container is chaning.

    If it's not, could you explain the typical usage of both?

    foreach - I don't use it anymore. But in general, you can use it safely with all Qt containers. It will be efficient and safe. If you use it on STL containers, you will experience a performance hit (poor performance).

    ranged for - I use it for both STL and Qt containers. The only thing to remember is that Qt containers have to be const, like this:

    for (const auto &item : qAsConst(list)) {
    }
    

    The item can be mutable. But the list has to be const, otherwise the container will detach and do a deep copy.

    Other than that, ranged for is good for all container types, it's fast and compilers can optimize it well.

    I need to add one final hint, though: for small containers, it all does not matter much. Modern computers are so fast, that if you use for wrongly, the performance penalty will be in nanoseconds or miliseconds tops. Only for big containers (hundreds, thousands of items etc.) it becomes important to use the loop correctly.



  • @sierdzio
    The following type of construct does not detach/copy, does it?

    const QVector<int> &intVec;
    for (int i : intVec)
    

  • Moderators

    @JonB said in Conflict in Qt Doc on the usage of foreach keyword and range-based for?:

    @sierdzio
    The following type of construct does not detach/copy, does it?

    const QVector<int> &intVec;
    for (int i : intVec)
    

    This is safe, yes.



  • @sierdzio Thanks for your reply!
    But I'm still having some questions:
    1.

    The item can be mutable. But the list has to be const,

    What does this mean? How can item be mutable when list is const? Are you saying about mutable member of item?

    2.

    otherwise the container will detach and do a deep copy.

    When will the container detach? Will it immediately detach when I use a non-const reference on its item?

    3.
    Will foreach do a deep copy if list is not const? If not, why not?
    I've read the source code of Q_FOREACH in qglobal.h. Expect that it copy the container first, it seems much like what ranged for really do then (using begin() and end()), am I wrong?


  • Moderators

    @Xeonacid said in Conflict in Qt Doc on the usage of foreach keyword and range-based for?:

    @sierdzio Thanks for your reply!
    But I'm still having some questions:
    1.

    The item can be mutable. But the list has to be const,

    What does this mean? How can item be mutable when list is const? Are you saying about mutable member of item?

    Item can be a non-const copy.

    const QVector<int> &intVec;
    for (int item : intVect) {
      // Item can change here! But it is a COPY, it won't affect the container
      item += 42;
    }
    

    2.

    otherwise the container will detach and do a deep copy.

    When will the container detach? Will it immediately detach when I use a non-const reference on its item?

    I think the detach happens when you enter the loop, even if you use a const reference to the item. That's why it's super important to keep the container const. More info with all the gory details: https://www.kdab.com/goodbye-q_foreach/

    3.
    Will foreach do a deep copy if list is not const? If not, why not?
    I've read the source code of Q_FOREACH in qglobal.h. It seems much like what ranged for do really (using begin() and end()), am I wrong?

    As far as I know, it will not do a deep copy unless absolutely necessary.



  • @sierdzio Many thanks!