C++ Qt:是否可以在使用 foreach 宏进行迭代时删除 QList 元素?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8613737/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 18:52:21  来源:igfitidea点击:

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

c++qtforeachqlist

提问by Dan

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

我是 Qt 的新手,正在尝试学习习语。

The foreachdocumentationsays:

foreach文件说:

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.

当 Qt 进入 foreach 循环时,它会自动获取容器的副本。如果在迭代时修改容器,则不会影响循环。

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

但它没有说明如何在使用foreach. 我最好的猜测是这样的:

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

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

必须idx在循环之外进行作用域(并且必须维护一个单独的循环计数器)似乎很丑陋。

Also, I know that foreachmakes 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.

另外,我知道foreach制作 的副本QList,这很便宜,但是一旦我删除了一个元素会发生什么 - 仍然便宜还是正在进行昂贵的修改时复制?是的,发生了深拷贝

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

编辑:这似乎也不是惯用的 Qt。

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

回答by Igor Oks

You should better use iteratorsfor that:

您应该更好地使用迭代器

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

回答by Mat

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 QListinstead of a QLinkedList.)

(并确保您真的想使用 aQList而不是 a QLinkedList。)

foreachis 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.

foreach当你想遍历一个集合进行检查时真的很好,但正如你所发现的,很难推理何时要更改底层集合的结构(而不​​是存储在那里的值)。所以在这种情况下我避免使用它,仅仅是因为我无法确定它是否安全或发生了多少复制开销。

回答by alexisdm

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

如果测试函数是可重入的,您还可以使用 QtConcurrent 删除“坏”元素:

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

Or the STL variant:

或 STL 变体:

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