概述

如果只想按顺序遍历容器中的所有项,可以使用Qt的foreach关键字。关键字是c++语言中特定于qt的附加项,使用预处理器实现。
它的语法是:foreach(变量,容器)语句。例如,下面是如何使用foreach来迭代QLinkedList<QString>:

QLinkedList<QString> list;
  ...
  QString str;
  foreach (str, list)
      qDebug() << str;

foreach代码明显短于使用迭代器的等效代码:

QLinkedList<QString> list;
  ...
  QLinkedListIterator<QString> i(list);
  while (i.hasNext())
      qDebug() << i.next();

除非数据类型包含逗号(例如,QPair<int, int>),否则用于迭代的变量可以在foreach语句中定义:

QLinkedList<QString> list;
  ...
  foreach (const QString &str, list)
      qDebug() << str;

像任何其他c++循环结构一样,可以在foreach循环的主体周围使用大括号,并且可以使用break离开循环:

QLinkedList<QString> list;
  ...
  foreach (const QString &str, list) {
      if (str.isEmpty())
          break;
      qDebug() << str;
  }

对于QMap和QHash, foreach会自动访问(键、值)对的值组件,因此不应该在容器上调用values()(它会生成一个不必要的副本,见下文)。如果想遍历键和值,可以使用迭代器(更快),或者你可以获取键,并使用它们来获取值:

QMap<QString, int> map;
  ...
  foreach (const QString &str, map.keys())
      qDebug() << str << ':' << map.value(str);

以下是使用QMultiMap示例:

QMultiMap<QString, int> map;
  ...
  foreach (const QString &str, map.uniqueKeys()) {
      foreach (int i, map.values(str))
          qDebug() << str << ':' << i;
  }

Qt在进入foreach循环时自动获取容器的副本。如果在迭代时修改容器,则不会影响循环。(如果不修改容器,复制仍然会发生,但是由于隐式共享,复制容器非常快。)
由于foreach创建了容器的副本,因此使用变量的非const引用不允许修改原始容器。它只影响拷贝,这可能不是你想要的。
Qt的foreach循环的另一种选择是基于范围的循环,这是c++ 11及更新版本的一部分。但是,请记住,基于范围的for可能会强制Qt容器分离,而foreach则不会。但是使用foreach总是复制容器,这对于STL容器来说通常并不便宜。如果有疑问,对于Qt容器首选foreach,对于STL容器首选range based for。
除了foreach, Qt还为无限循环提供了一个forever伪关键字:

forever {
      ...
  }

如果担心命名空间干扰,可以通过在你的.pro文件中添加以下一行来禁用这些宏:

CONFIG += no_keywords

结论

你就算失败了99次,也要再努力一次,凑个整数