【问题标题】:Qt: is removing QList elements while iterating using foreach macro possible?Qt:在使用 foreach 宏进行迭代时是否可以删除 QList 元素?
【发布时间】:2012-01-26 16:14:27
【问题描述】:

我是 Qt 的新手,正在努力学习习语。

foreach documentation 说:

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

但它并没有说明 如何 在使用 foreach 进行迭代时删除元素。我最好的猜测是:

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

似乎很难将idx 限定在循环之外(并且必须维护一个单独的循环计数器)。

另外,我知道foreach 复制了QList,这很便宜,但是一旦我删除一个元素会发生什么 - 仍然很便宜还是有一个昂贵的复制-修改正在进行吗? 是的,deep copy happens

编辑:这看起来也不是惯用的 Qt。

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

【问题讨论】:

  • 为什么要使用foreach
  • @Mat,我不必使用foreach,它看起来很好用,文档似乎暗示有一些方法可以做到这一点。 Qt 似乎经过深思熟虑,我认为我正在尝试做的事情会有一些明显的习惯用法。
  • void QMutableListIterator::remove () 怎么样? developer.qt.nokia.com/doc/qt-4.8/…

标签: c++ qt foreach qlist


【解决方案1】:

你最好 use iterators 这样做:

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

【讨论】:

  • 文档说“Qt 应用程序中的标准......比 STL 更方便......效率略低”。好吧,三分之二还不错。谢谢!
【解决方案2】:

如果测试函数是可重入的,你也可以使用 QtConcurrent 来移除“坏”的元素:

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

或 STL 变体:

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

【讨论】:

  • 非常适合 lambda 函数,例如 blockingFilter(list, [](const Elem &amp; e) { return e.shouldBeKept(); });
【解决方案3】:

如果您根本不想要副本,请使用迭代器。比如:

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

(并确保您确实想使用QList 而不是QLinkedList。)

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

【讨论】:

  • 在大多数情况下,您不应该害怕使用 QList 而不是 QLinkedList。 QList 实际上也将其所有元素存储为指针。因此,追加、插入或删除元素并不像在 QVector 中那样昂贵。
猜你喜欢
  • 2013-09-01
  • 1970-01-01
  • 2015-04-03
  • 2010-10-10
  • 2010-12-05
  • 2019-11-04
  • 1970-01-01
相关资源
最近更新 更多