Qt:在使用foreach宏迭代的同时删除QList元素?

Dan*_*Dan 41 c++ foreach qt qlist

我是Qt的新手,并试图学习成语.

foreach文件说:

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

但它没有说明如何在迭代时删除元素foreach.我最好的猜测是这样的:

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

看起来很丑陋,不得不idx在循环外部(并且必须保持一个单独的循环计数器).

此外,我知道这foreach是一个QList便宜的副本,但是一旦我删除一个元素会发生什么 - 是否仍然便宜或是否有昂贵的复制修改?是的,深层复制发生了.

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

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

Igo*_*Oks 49

你应该更好地使用迭代器:

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

  • Docs说"Qt应用程序的标准......比STL更方便......效率稍差".好的,3分中有2分不错.谢谢! (3认同)

Mat*_*Mat 21

如果您根本不需要副本,请使用迭代器.就像是:

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

(并确保你真的想要使用QList而不是QLinkedList.)

foreach想要遍历集合进行检查时非常好,但正如您所发现的,当您想要更改底层集合的结构(而不​​是存储在那里的值)时,很难说明.所以我在那种情况下避免它,仅仅因为我无法弄清楚它是否安全或者复制开销有多少.


ale*_*sdm 11

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

#include <QtCore/QtConcurrentFilter>
...
QtConcurrent::blockingFilter(fooList, bad);
Run Code Online (Sandbox Code Playgroud)

或STL变体:

#include <algorithm>
...
fooList.erase(std::remove_if(fooList.begin(), fooList.end(), bad), 
              fooList.end());
Run Code Online (Sandbox Code Playgroud)