使用foreach循环修改Qt数据结构的正确方法



我正在使用foreach循环迭代QLinkedList,但如果项目符合特定条件,我需要删除它们。在不打乱循环的情况下,正确的方法是什么?

foreach( Object obj, myLinkedList )
{
    if( obj.val == BAD_VAL )
        // remove the item from myLinkedList
}

我发现了其他一些问题可以解决这个问题,但不适用于一般情况,如链表。

如果可能的话,我也想知道其他数据结构(如QSetQHash等)。感谢

对于特定情况:

显然,foreach循环根本不应该用于修改列表,因为foreach循环实际上是在原始列表的副本上工作。如果修改它,不仅会因为写入时的隐式共享和修改而受到惩罚,而且一旦退出循环,您的更改也会被丢弃。

实现这一点的正确方法是使用迭代器。我更喜欢Java风格的迭代器。您会注意到,每个列表类型都有提供简单迭代器的迭代器类。对于QLinkedList示例,存在一个类QMutableLinkedListIterator。它可以如下使用:

从Qt文档中添加了我的评论:

 QMutableLinkedListIterator<int> i(list); // pass list as argument
 while (i.hasNext()) { 
     int val = i.next();                  // retrieve value of current item
     if (val < 0) {
         i.setValue(-val);                // change/set value of current item
     } else if (val == 0) {
         i.remove();                      // delete current item
     }
 }


对于一般情况:

如果您使用的是QLinkedList以外的Qt数据结构,那么很可能有一个迭代器类。如果要修改列表,请使用可变版本。API对其中的每一个都是大致相同的。以下是类别:

Structure    |   Immutable Case       |  Mutable Case
-----------------------------------------------------
QList        |   QListIterator        |  QMutableListIterator 
QLinkedList  |   QLinkedListIterator  |  QMutableLinkedListIterator 
QHash        |   QHashIterator        |  QMutableHashIterator
QMap         |   QMapIterator         |  QMutableMapIterator 
QSet         |   QSetIterator         |  QMutableSetIterator 
QStringList  |   QStringListIterator  |  QMutableStringListIterator 
QVector      |   QVectorIterator      |  QMutableVectorIterator

我也可以建议一种昂贵但简单的方法来做到这一点。创建另一个列表并将好的对象复制到其中。然后用新列表替换旧列表。

QLinkedList<Object> new_list;
foreach(Object obj, myLinkedList) {
  if(obj.val != BAD_VAL) {
    new_list << obj;
  }
}
list = new_list;

如果您的列表内容很大,请不要这样做。

最新更新