web-dev-qa-db-ja.com

Qt:foreachマクロを使用して反復処理中にQList要素を削除できますか?

私はQtが初めてで、イディオムを学ぼうとしています。

foreach documentation の意味:

Qtは、foreachループに入ると、コンテナーのコピーを自動的に取得します。繰り返しながらコンテナを変更しても、ループには影響しません。

しかし、foreachで繰り返しながら要素を削除することはhowとは言いません。私の最高の推測は次のようなものです:

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

idxをループの外側にスコープする必要があるように(また、まったく別のループカウンターを維持する必要があるため)いようです。

また、foreachQListのコピーを作成することを知っていますが、これは安価ですが、要素を削除するとどうなりますか?変更を続けますか? はい、 ディープコピーが発生します

EDIT:これも慣用的なQtのようには見えません。

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

より良い イテレータを使用 する必要があります:

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

コピーがまったく必要ない場合は、反復子を使用します。何かのようなもの:

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

(そして、本当にQListの代わりにQLinkedListを使用したいことを確認してください。)

foreachは、検査のためにコレクションを走査したい場合は本当に素晴らしいですが、あなたが見つけたように、基礎となるコレクションの構造(そこに格納された値ではない)をいつ変更したいかを考えるのは難しいです。そのため、安全かどうか、またはコピーのオーバーヘッドがどれだけ発生するかわからないという理由だけで、その場合は回避します。

21
Mat

テスト関数がリエントラントの場合、QtConcurrentを使用して「不良」要素を削除することもできます。

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

または、STLバリアント:

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