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

时间:2013-07-05 17:29:51

标签: c++ qt foreach qt4 iterator

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

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

我发现other questions可以解决这个问题,但不适用于链接列表等一般情况。

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

2 个答案:

答案 0 :(得分:16)

针对具体案例:

显然不应使用foreach循环来修改列表,因为foreach循环实际上正在处理原始列表的副本。如果你修改它,不仅会因为隐式共享和写入时修改而受到惩罚,但是一旦你退出循环,你的更改也会被丢弃。

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

添加了我的评论Qt documentation

 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数据结构,很可能会有一个迭代器类供你使用。如果要修改列表,请使用Mutable版本。每种API的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

答案 1 :(得分:0)

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

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

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