“for”循环与 C++ 中 Qt 的“foreach”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/771008/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 17:12:36  来源:igfitidea点击:

'for' loop vs Qt's 'foreach' in C++

c++performanceqtforeachfor-loop

提问by Ajay

Which is better (or faster), a C++ forloop or the foreachoperator provided by Qt? For example, the following condition

C++for循环或foreachQt 提供的运算符哪个更好(或更快)?例如,以下条件

QList<QString> listofstrings;

Which is better?

哪个更好?

foreach(QString str, listofstrings)
{
    //code
}

or

或者

int count = listofstrings.count();
QString str = QString();
for(int i=0;i<count;i++)
{
    str = listofstrings.at(i);
    //Code
}

回答by paxdiablo

It really doesn't matter in most cases.

在大多数情况下,这真的无关紧要。

The large number of questions on StackOverflow regarding whether this method or that method is faster, belie the fact that, in the vast majority of cases, code spends most of its time sitting around waiting for users to do something.

StackOverflow 上关于这种方法或那种方法是否更快的大量问题表明,在绝大多数情况下,代码大部分时间都在等待用户做某事。

If you arereally concerned, profile it for yourself and act on what you find.

如果你真的关心,个人资料是为了你自己和你发现了什么行动。

But I think you'll most likely find that only in the most intense data-processing-heavy work does this question matter. The difference may well be only a couple of seconds and even then, only when processing huge numbers of elements.

但我认为您很可能会发现,只有在最密集的数据处理工作中,这个问题才有意义。差异很可能只有几秒钟,即使如此,也只有在处理大量元素时。

Get your code working first. Then get it working fast(and only if you find an actual performance issue).

让你的代码工作第一。然后让它快速工作(并且只有当你发现一个实际的性能问题时)。

Time spent optimising before you've finished the functionality and can properly profile, is mostly wasted time.

在完成功能并可以正确分析之前花费的时间优化,主要是浪费时间。

回答by Parker Coates

First off, I'd just like to say I agree with Pax, and that the speed probably doesn't enter into it. foreach wins hands down based on readability, and that's enough in 98% of cases.

首先,我只想说我同意Pax,而且速度可能没有考虑在内。基于可读性,foreach 胜出,这在 98% 的情况下就足够了。

But of course the Qt guys have looked into it and actually done some profiling: http://blog.qt.io/blog/2009/01/23/iterating-efficiently/

但当然 Qt 人已经研究过它并实际上做了一些分析:http: //blog.qt.io/blog/2009/01/23/iterating-efficiently/

The main lesson to take away from that is: use const references in read only loops as it avoids the creation of temporary instances. It also make the purpose of the loop more explicit, regardless of the looping method you use.

从中吸取的主要教训是:在只读循环中使用 const 引用,因为它避免了创建临时实例。它还使循环的目的更加明确,无论您使用何种循环方法。

回答by Evan Teran

It really doesn't matter. Odds are if your program is slow, this isn't the problem. However, it should be noted that you aren't make a completely equal comparison. Qt's foreachis more similar to this (this example will use QList<QString>):

真的没关系。如果你的程序很慢,这不是问题所在。但是,应该注意的是,您并没有进行完全平等的比较。Qtforeach与此更相似(此示例将使用QList<QString>):

for(QList<QString>::iterator it = Con.begin(); it != Con.end(); ++it) {
    QString &str = *it;
    // your code here
}

The macro is able to do this by using some compiler extensions (like GCC's __typeof__) to get the type of the container passed. Also imagine that boost's BOOST_FOREACHis very similar in concept.

宏能够通过使用一些编译器扩展(如 GCC 的__typeof__)来获取传递的容器类型来做到这一点。还要想象一下,boostBOOST_FOREACH在概念上非常相似。

The reason why your example isn't fair is that your non-Qt version is adding extra work.

你的例子不公平的原因是你的非 Qt 版本增加了额外的工作。

You are indexing instead of really iterating. If you are using a type with non-contiguous allocation (I suspect this might be the case with QList<>), then indexing will be more expensive since the code has to calculate "where" the n-th item is.

您正在索引而不是真正迭代。如果您使用的是具有非连续分配的类型(我怀疑 可能是这种情况QList<>),那么索引将更加昂贵,因为代码必须计算第 n 项的“位置”。

That being said. It stilldoesn't matter. The timing difference between those two pieces of code will be negligible if existent at all. Don't waste your time worrying about it. Write whichever you find more clear and understandable.

话虽如此。它仍然没有关系。如果存在的话,这两段代码之间的时间差异将可以忽略不计。不要浪费你的时间来担心它。写下你觉得更清楚易懂的那个。

EDIT:As a bonus, currently I strongly favor the C++11 version of container iteration, it is clean, concise and simple:

编辑:作为奖励,目前我非常喜欢容器迭代的 C++11 版本,它干净、简洁和简单:

for(QString &s : Con) {
    // you code here
}

回答by Evan Teran

I don't want to answer the question which is faster, but I do want to say which is better.

我不想回答哪个更快,但我想说哪个更好。

The biggest problem with Qt's foreach is the fact that it takes a copy of your container before iterating over it. You could say 'this doesn't matter because Qt classes are refcounted' but because a copy is used you don't actually change your original container at all.

Qt 的 foreach 最大的问题是它在迭代之前获取容器的副本。您可以说“这无关紧要,因为 Qt 类已被引用”,但由于使用了副本,因此您实际上根本不会更改原始容器。

In summary, Qt's foreach can only be used for read-only loops and thus should be avoided. Qt will happily let you write a foreach loop which you think will update/modify your container but in the end all changes are thrown away.

总之,Qt 的 foreach 只能用于只读循环,因此应该避免使用。Qt 很乐意让您编写一个 foreach 循环,您认为它会更新/修改您的容器,但最终所有更改都会被丢弃。

回答by ymoreau

Since Qt 5.7the foreachmacro is deprecated, Qt encourages you to use the C++11 forinstead.
http://doc.qt.io/qt-5/qtglobal.html#foreach

由于Qt的5.7foreach宏已被弃用,QT鼓励您使用C ++ 11for来代替。
http://doc.qt.io/qt-5/qtglobal.html#foreach

(more details about the difference here : https://www.kdab.com/goodbye-q_foreach/)

(有关差异的更多详细信息:https: //www.kdab.com/goodbye-q_foreach/

回答by jalf

First, I completely agree with the answer that "it doesn't matter". Pick the cleanest solution, and optimize if it becomes a problem.

首先,我完全同意“没关系”的答案。选择最干净的解决方案,并在它成为问题时进行优化。

But another way to look at it is that often, the fastest solution is the one that describes your intent most accurately. In this case, QT's foreach says that you'd like to apply some action for each element in the container.

但另一种看待它的方式是,最快的解决方案通常是最准确地描述您的意图的解决方案。在这种情况下,QT 的 foreach 表示您希望对容器中的每个元素应用一些操作。

A plain for loop say that you'd like a counter i. You want to repeatedly add one to this value i, and as long as it is less than the number of elements in the container, you would like to perform some action.

一个简单的 for 循环说你想要一个 counter i。你想对这个值 i 重复加 1,只要它小于容器中的元素数,你就想执行一些操作。

In other words, the plain for loop overspecifies the problem. It adds a lot of requirements that aren't actually part of what you're trying to do. You don't careabout the loop counter. But as soon as you write a for loop, it has to be there.

换句话说,普通的 for 循环过度说明了问题。它增加了许多实际上并不是您尝试做的事情的一部分的要求。你不关心循环计数器。但是一旦你写了一个 for 循环,它就必须在那里。

On the other hand, the QT people have made no additional promises that may affect performance. They simply guarantee to iterate through the container and apply an action to each.

另一方面,QT 人员没有做出可能影响性能的额外承诺。它们只是保证遍历容器并对每个容器应用一个操作。

In other words, often the cleanest and most elegant solution is also the fastest.

换句话说,通常最干净、最优雅的解决方案也是最快的。

回答by Bilderbikkel

A benchmark, and its results, on this can be found at http://richelbilderbeek.nl/CppExerciseAddOneAnswer.htm

可以在http://richelbilderbeek.nl/CppExerciseAddOneAnswer.htm上找到一个基准及其结果

IMHO (and many others here) it (that is speed) does not matter.

恕我直言(以及这里的许多其他人)它(即速度)无关紧要。

But feel free to draw your own conclusions.

但请随意得出自己的结论。

回答by justinhj

The foreach from Qt has a clearer syntax for the for loop IMHO, so it's better in that sense. Performance wise I doubt there's anything in it.

Qt 的 foreach 对 for 循环有更清晰的语法恕我直言,所以从这个意义上说它更好。性能方面我怀疑里面有什么。

You could consider using the BOOST_FOREACHinstead, as it is a well thought out fancy for loop, and it's portable (and presumably will make it's way into C++ some day and is future proof too).

您可以考虑使用BOOST_FOREACH代替,因为它是一个经过深思熟虑的花哨的 for 循环,并且它是可移植的(并且可能有一天会进入 C++ 并且也是面向未来的证明)。

回答by Foredecker

For small collections, it should matter and foreach tends to be clearer.

对于小型集合,它应该很重要并且 foreach 往往更清晰。

However, for larger collections, for will begin to beat foreach at some point. (assuming that the 'at()' operator is efficient.

但是,对于较大的集合,for 将在某个时候开始击败 foreach。(假设 'at()' 运算符是有效的。

If this is really important (and I'm assuming it is since you are asking) then the best thing to do is measure it. A profiler should do the trick, or you could build a test version with some instrumentation.

如果这真的很重要(我假设这是因为你在问)那么最好的办法就是衡量它。分析器应该可以解决问题,或者您可以使用一些工具构建测试版本。

回答by Darren Clark

I would expect foreach to work nominally faster in some cases, and the about same in others, except in cases where the items are an actual array in which case the performace difference is negligible.

我希望 foreach 在某些情况下名义上更快地工作,而在其他情况下也差不多,除非项目是实际数组,在这种情况下,性能差异可以忽略不计。

If it is implemented on top of an enumerator, it maybe more efficient than a straight indexing, depending on implementation. It's unlikely to be less efficient. For example, if someone exposed a balanced tree as both indexable and enumerable, then foreach will be decently faster. This is because each index will have to independently find the referenced item, while an enumerator has the context of the current node to more efficiently navigate to the next ont.

如果它是在枚举器之上实现的,它可能比直接索引更有效,具体取决于实现。它不太可能效率较低。例如,如果有人将平衡树公开为可索引和可​​枚举,那么 foreach 会更快。这是因为每个索引都必须独立地找到引用的项目,而枚举器具有当前节点的上下文以更有效地导航到下一个 ont。

If you have an actual array, then it depends on the implementation of the language and class whether foreach will be faster for the same as for.

如果您有一个实际的数组,那么 foreach 是否与 for 相同取决于语言和类的实现。

If indexing is a literal memory offset(such as C++), then for should be marginally faster since you're avoiding a function call. If indexing is an indirection just like a call, then it should be the same.

如果索引是文字内存偏移量(例如 C++),那么 for 应该稍微快一点,因为您避免了函数调用。如果索引就像调用一样是间接的,那么它应该是相同的。

All that being said... I find it hard to find a case for generalization here. This is the last sort of optimization you should be looking for, even if there is a performance problem in your application. If you have a performance problem that can be solved by changing how you iterate, you don't really have a performance problem. You have a BUG, because someone wrote either a really crappy iterator, or a really crappy indexer.

说了这么多......我发现在这里很难找到一个概括的案例。这是您应该寻找的最后一种优化,即使您的应用程序中存在性能问题。如果您的性能问题可以通过更改迭代方式来解决,那么您就没有真正的性能问题。你有一个 BUG,因为有人写了一个非常糟糕的迭代器,或者一个非常糟糕的索引器。