[英]'for' loop vs Qt's 'foreach' in 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上的大量問題,認為在絕大多數情況下,代碼花費大部分時間等待用戶做某事。
如果你真的關心,簡介為自己和作用於你的發現。
但我認為你很可能會發現,只有在最激烈的數據處理工作中,這個問題才能解決。 只有在處理大量元素時,差異可能只有幾秒甚至更長時間。
讓代碼先運行 。 然后讓它快速運行 (並且只有在您發現實際性能問題時)。
在完成功能之前花費時間進行優化並且可以正確分析,這主要是浪費時間。
首先,我只想說我同意Pax,並且速度可能不會進入它。 foreach基於可讀性贏得了勝利,這在98%的情況下都足夠了。
但是當然Qt的人已經調查了它並且實際上做了一些分析: http : //blog.qt.io/blog/2009/01/23/iterating-efficiently/
從中學到的主要教訓是:在只讀循環中使用const引用,因為它避免了臨時實例的創建。 無論您使用何種循環方法,它還使循環的目的更明確。
這沒關系 。 可能的情況是你的程序很慢,這不是問題。 但是,應該注意的是,你並沒有做出完全相同的比較。 Qt的foreach
更類似於此(此示例將使用QList<QString>
):
for(QList<QString>::iterator it = Con.begin(); it != Con.end(); ++it) {
QString &str = *it;
// your code here
}
宏可以通過使用一些編譯器擴展(如GCC的__typeof__
)來獲取傳遞的容器類型。 還想象一下boost的BOOST_FOREACH
在概念上非常相似。
你的例子不公平的原因是你的非Qt版本正在增加額外的工作。
您正在編制索引而不是實際迭代。 如果您使用的是具有非連續分配的類型(我懷疑這可能是QList<>
的情況),那么索引將更加昂貴,因為代碼必須計算第n個項目的“where”。
話雖如此。 它仍然沒關系。 如果存在的話,這兩段代碼之間的時間差異可以忽略不計。 不要浪費你的時間擔心它。 寫下你發現的更清晰易懂的內容。
編輯:作為獎勵,目前我非常支持C ++ 11版本的容器迭代,它簡潔明了:
for(QString &s : Con) {
// you code here
}
我不想回答更快的問題,但我想說哪個更好。
Qt的foreach最大的問題是它在迭代之前需要一個容器的副本。 您可以說'這無關緊要,因為Qt類已被重新計算',但由於使用了副本,您根本不會實際更改原始容器。
總之,Qt的foreach只能用於只讀循環,因此應該避免使用。 Qt很樂意讓你編寫一個foreach循環,你認為它會更新/修改你的容器,但最后所有的變化都會被拋棄。
由於Qt的5.7 foreach
宏已被棄用,QT鼓勵您使用C ++ 11 for
替代。
http://doc.qt.io/qt-5/qtglobal.html#foreach
(有關差異的更多詳細信息,請訪問: https : //www.kdab.com/goodbye-q_foreach/ )
首先,我完全贊同“無所謂”的答案。 選擇最干凈的解決方案,並優化是否成為問題。
但另一種看待它的方法是,最快的解決方案通常是最准確地描述您的意圖的解決方案。 在這種情況下,QT的foreach表示您希望對容器中的每個元素應用一些操作。
一個普通的循環說你想要一個反擊i
。 您希望重復向此值i添加一個,並且只要它小於容器中的元素數,您就可以執行某些操作。
換句話說,plain for循環過度指定了問題。 它增加了許多要求,而這些要求實際上並不是您要做的事情的一部分。 你不關心循環計數器。 但是只要你編寫一個for循環,就必須在那里。
另一方面,QT人員沒有做出可能影響績效的額外承諾。 它們只是保證迭代容器並對每個容器應用一個動作。
換句話說,通常最干凈,最優雅的解決方案也是最快的。
關於此的基准及其結果可以在http://richelbilderbeek.nl/CppExerciseAddOneAnswer.htm找到。
恕我直言(以及其他許多人)它(即速度)並不重要。
但請隨意得出自己的結論。
來自Qt的foreach有一個更清晰的for循環恕我直言的語法,所以在這個意義上它更好。 表現明智我懷疑它有什么。
您可以考慮使用BOOST_FOREACH ,因為它是一個經過深思熟慮的循環,並且它是可移植的(並且可能會讓它在某天進入C ++並且也是未來的證明)。
對於小型館藏來說,它應該是重要的,而且預期往往更清晰。
然而,對於較大的收藏品,將在某些時候開始擊敗foreach。 (假設'at()'運算符是有效的。
如果這非常重要(我假設它是你要求的那樣),那么最好的辦法就是衡量它。 分析器應該可以解決問題,或者您可以使用一些檢測來構建測試版本。
我希望foreach在某些情況下名義上更快,而在其他情況下大致相同,除非項目是實際數組,在這種情況下,性能差異可以忽略不計。
如果它是在枚舉器之上實現的,則它可能比直接索引更有效,具體取決於實現。 它不太可能效率低下。 例如,如果有人將平衡樹暴露為可索引和可枚舉的,那么foreach將會更加快速。 這是因為每個索引必須獨立地找到引用的項,而枚舉器具有當前節點的上下文以更有效地導航到下一個ont。
如果你有一個實際的數組,那么它取決於語言和類的實現是否foreach將更快與for。相同。
如果索引是一個文字內存偏移量(例如C ++),那么因為你要避免函數調用,所以應該稍微快一點。 如果索引是一個間接,就像一個調用,那么它應該是相同的。
所有這一切......我發現很難找到一個概括的案例。 這是您應該尋找的最后一種優化,即使您的應用程序存在性能問題。 如果您遇到可以通過更改迭代方式來解決的性能問題,那么您實際上並沒有遇到性能問題。 你有一個BUG,因為有人寫了一個非常糟糕的迭代器,或者一個非常糟糕的索引器。
您可以查看STL的for_each函數。 我不知道它是否會比你提出的兩個選項更快,但它比Qt foreach更標准化,並避免了你可能遇到的常規for循環的一些問題(即越界索引和困難)將循環轉換為不同的數據結構)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.