Qt: is removing QList elements while iterating using foreach macro possible?

你说的曾经没有我的故事 提交于 2019-12-18 12:45:12

问题


I'm new to Qt and trying to learn the idioms.

The foreach documentation says:

Qt automatically takes a copy of the container when it enters a foreach loop. If you modify the container as you are iterating, that won't affect the loop.

But it doesn't say how to remove an element while iterating with foreach. My best guess is something like:

int idx = 0;
foreach (const Foo &foo, fooList) {
  if (bad(foo)) {
    fooList.removeAt(idx);
  }
  ++idx;
}

Seems ugly to have to scope idx outside the loop (and to have to maintain a separate loop counter at all).

Also, I know that foreach makes a copy of the QList, which is cheap, but what happens once I remove an element -- is that still cheap or is there an expensive copy-on-modify going on? Yes, deep copy happens.

EDIT : This doesn't seem like idiomatic Qt either.

for (int idx = 0; idx < fooList.size(); ) {
  const Foo &foo = fooList[idx];
  if (bad(foo)) {
    fooList.removeAt(idx);
  }
  else ++idx;
}

回答1:


You should better use iterators for that:

// Remove all odd numbers from a QList<int> 
QMutableListIterator<int> i(list);
while (i.hasNext()) {
    if (i.next() % 2 != 0)
        i.remove();
}



回答2:


If you don't want a copy at all, use iterators. Something like:

QList<yourtype>::iterator it = fooList.begin();
while (it != fooList.end()) {
  if (bad(*it))
    it = fooList.erase(it);
  else
    ++it;
}

(And make sure you really want to use a QList instead of a QLinkedList.)

foreach is really nice when you want to traverse a collection for inspection, but as you have found, it's hard to reason about when you want to change the structure of the underlying collection (not the values stored in there). So I avoid it in that case, simply because I can't figure out if it is safe or how much copying overhead happens.




回答3:


If the test function is reentrant, you could also use QtConcurrent to remove the "bad" elements:

#include <QtCore/QtConcurrentFilter>
...
QtConcurrent::blockingFilter(fooList, bad);

Or the STL variant:

#include <algorithm>
...
fooList.erase(std::remove_if(fooList.begin(), fooList.end(), bad), 
              fooList.end());


来源:https://stackoverflow.com/questions/8613737/qt-is-removing-qlist-elements-while-iterating-using-foreach-macro-possible

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!