私はQtが初めてで、イディオムを学ぼうとしています。
Qtは、foreachループに入ると、コンテナーのコピーを自動的に取得します。繰り返しながらコンテナを変更しても、ループには影響しません。
しかし、foreach
で繰り返しながら要素を削除することはhowとは言いません。私の最高の推測は次のようなものです:
int idx = 0;
foreach (const Foo &foo, fooList) {
if (bad(foo)) {
fooList.removeAt(idx);
}
++idx;
}
idx
をループの外側にスコープする必要があるように(また、まったく別のループカウンターを維持する必要があるため)いようです。
また、 はい、 ディープコピーが発生します 。foreach
はQList
のコピーを作成することを知っていますが、これは安価ですが、要素を削除するとどうなりますか?変更を続けますか?
EDIT:これも慣用的なQtのようには見えません。
for (int idx = 0; idx < fooList.size(); ) {
const Foo &foo = fooList[idx];
if (bad(foo)) {
fooList.removeAt(idx);
}
else ++idx;
}
より良い イテレータを使用 する必要があります:
// Remove all odd numbers from a QList<int>
QMutableListIterator<int> i(list);
while (i.hasNext()) {
if (i.next() % 2 != 0)
i.remove();
}
コピーがまったく必要ない場合は、反復子を使用します。何かのようなもの:
QList<yourtype>::iterator it = fooList.begin();
while (it != fooList.end()) {
if (bad(*it))
it = fooList.erase(it);
else
++it;
}
(そして、本当にQList
の代わりにQLinkedList
を使用したいことを確認してください。)
foreach
は、検査のためにコレクションを走査したい場合は本当に素晴らしいですが、あなたが見つけたように、基礎となるコレクションの構造(そこに格納された値ではない)をいつ変更したいかを考えるのは難しいです。そのため、安全かどうか、またはコピーのオーバーヘッドがどれだけ発生するかわからないという理由だけで、その場合は回避します。
テスト関数がリエントラントの場合、QtConcurrentを使用して「不良」要素を削除することもできます。
#include <QtCore/QtConcurrentFilter>
...
QtConcurrent::blockingFilter(fooList, bad);
または、STLバリアント:
#include <algorithm>
...
fooList.erase(std::remove_if(fooList.begin(), fooList.end(), bad),
fooList.end());