'for'循环与Qt的'foreach'在C ++中
哪个更好(或更快),C ++ for
循环还是由Qt提供的foreach
运算符? 例如,下面的条件
QList<QString> listofstrings;
哪个更好?
foreach(QString str, listofstrings) { //code }
要么
int count = listofstrings.count(); QString str = QString(); for(int i=0;i<count;i++) { str = listofstrings.at(i); //Code }
在大多数情况下,这并不重要。
有关StackOverflow的大量问题,关于这种方法或方法是否更快,认为在绝大多数情况下,代码大部分时间都在等待用户执行某些操作。
如果您真的担心,请自行描述并根据您的发现采取行动。
但是我想你很可能会发现,只有在数据处理最繁重的工作中,这个问题才是重要的。 只有在处理大量元素时,差异可能只有几秒钟,甚至在那个时候。
让你的代码先工作。 然后让它工作得很快 (只有当你发现一个实际的性能问题)。
在完成function并正确configuration之前花费的时间大多是浪费时间。
首先,我只想说我同意Pax,速度可能不会达成。 foreach以可读性为基础赢得了胜利,这在98%的情况下已经足够了。
但是当然Qt的人已经研究过,并且实际上做了一些分析: http : //blog.qt.io/blog/2009/01/23/iterating-efficiently/
主要的教训是:在只读循环中使用const引用,因为它避免了创build临时实例。 无论您使用何种循环方法,它也会使循环的目的更为明确。
这真的没关系 。 如果你的程序很慢,可能性不大,这不是问题。 但是,应该指出,你并没有完全平等的比较。 Qt的foreach
更类似于这个(这个例子将使用QList<QString>
):
for(QList<QString>::iterator it = Con.begin(); it != Con.end(); ++it) { QString &str = *it; // your code here }
macros能够通过使用一些编译器扩展(如GCC的__typeof__
)来获取传递的容器的types。 另外想象一下,boost的BOOST_FOREACH
在概念上非常相似。
你的例子不公平的原因是你的非Qt版本增加了额外的工作。
你是索引而不是真正的迭代。 如果你正在使用非连续分配的types(我怀疑这可能是QList<>
的情况),那么索引将会更加昂贵,因为代码必须计算第n个项目的“where”。
话虽如此。 这仍然没有关系。 如果存在的话,这两个代码之间的时间差异将是可以忽略不计的。 不要浪费你的时间担心。 写出来,你发现更清楚和可以理解的。
编辑:作为奖金,目前我强烈支持C ++ 11版本的容器迭代,它很干净,简洁,简单:
for(QString &s : Con) { // you code here }
我不想回答这个问题,但我想说哪个更好。
Qt的foreach最大的问题是它在迭代之前需要一个容器的副本。 你可以说'这不重要,因为Qt类是refcounted',但因为使用副本,你根本不会改变你的原始容器。
总之,Qt的foreach只能用于只读循环,因此应该避免。 Qt会高兴地让你写一个foreach循环,你认为它会更新/修改你的容器,但最后所有的变化都被抛弃了。
首先,我完全同意“没关系”的答案。 select最干净的解决scheme,并优化,如果它成为一个问题。
但是另一种看待它的方法是,最快的解决scheme通常是最准确地描述你的意图的解决scheme。 在这种情况下,QT的foreach说,你想对容器中的每个元素应用一些动作。
一个简单的循环说,你想要一个柜台i
。 你想重复给这个值添加一个值,只要它less于容器中的元素数量,你想要执行一些操作。
换句话说,for循环指出了这个问题。 它增加了许多实际上并不是你所要做的一部分的要求。 你不关心循环计数器。 但是一旦你写了一个for循环,就必须在那里。
另一方面,QT人没有作出任何可能影响performance的承诺。 他们只是保证遍历容器并对每个容器应用一个动作。
换句话说,最干净最优雅的解决scheme也是最快的。
从Qt的foreach有更清晰的for循环恕我直言,所以它在这个意义上更好。 性能明智,我怀疑它有什么。
你可以考虑使用BOOST_FOREACH ,因为它是一个深思熟虑的循环,它是可移植的(大概会使它有一天进入C ++的方式,也是未来的certificate)。
基准及其结果可以在http://richelbilderbeek.nl/CppExerciseAddOneAnswer.htm上find
恕我直言(和其他许多人在这里)它(这是速度)并不重要。
但随时可以得出自己的结论。
对于小型collections品来说,这应该是重要的,而且每一个趋势都会更加清晰。
然而,对于较大的collections品,在某些时候会开始摔打。 (假设'at()'操作符是有效的。
如果这真的很重要(我假设这是因为你问),那么最好的办法是衡量它。 一个分析器应该做的伎俩,或者你可以用一些仪器build立一个testing版本。
由于Qt 5.7中的foreach
macros已被弃用,Qt鼓励您使用C ++ 11 for
代替。
http://doc.qt.io/qt-5/qtglobal.html#foreach
(有关这里的差异的更多细节: https : //www.kdab.com/goodbye-q_foreach/ )
你可以看看STL的for_each函数。 我不知道它是否会比你提出的两个选项更快,但是它比Qt foreach更加标准化,并且避免了你可能遇到的一些常规for循环的问题(即超出边界索引和困难将循环转换为不同的数据结构)。
我希望在某些情况下,foreach的名义工作速度更快,其他情况下的速度更快,除非这些项目是实际的数组,在这种情况下,性能差异可以忽略不计。
如果它是在枚举器之上实现的,则可能比直接索引更有效,具体取决于实现。 这不太可能效率不高。 例如,如果有人将平衡树暴露为可索引和可枚举,那么foreach将体面得更快。 这是因为每个索引将不得不独立地find引用的项目,而枚举器具有当前节点的上下文以更有效地导航到下一个ont。
如果你有一个实际的数组,那么这取决于语言和类的实现,foreach是否会更快。
如果索引是一个字面的内存偏移量(如C ++),那么应该稍微快一点,因为你避免了一个函数调用。 如果索引是一个间接就像一个调用,那么它应该是相同的。
所有这一切说…我觉得这里很难find一个普遍的情况。 即使您的应用程序出现性能问题,这也是您应该寻找的最后一种优化方式。 如果你有一个性能问题可以通过改变迭代的方式来解决,你并没有真正的性能问题。 你有一个BUG,因为有人写了一个非常糟糕的迭代器,或者一个非常糟糕的索引器。