[英]Read-only ranged based for
讓我們考慮下面的例子(當然應該用std::accumulate
代替):
#include <vector>
auto sum(std::vector<int> const& numbers) -> int
{
auto sum = 0;
for(auto /*const, const&, &&, [nothing]*/ i : numbers) { sum += i; }
return sum;
}
如您所見,有許多不同的方法可以將基於范圍的 for 循環用於小類型。 請注意,所有這些變體都使用gcc
在編譯器資源管理器中編譯為相同的匯編代碼。
我經常看到在第一種情況下使用auto i
和在第二種情況下使用auto const& i
的建議。
但我們正在與編譯器而不是這里的人交談。 有趣的信息是變量只是輸入。 這不是由auto i
表示的。
那么在只需要讀取輸入的任何情況下,使用auto const& i
而不是auto i
是否有任何性能劣勢?
不要想太多。 在 C 和 C++ 中有“AS IF RULE”,這會導致您的示例的任何版本都不會導致生成的機器代碼發生任何變化。
看到這個神螺栓: https://godbolt.org/z/3rnWrr解釋:注意每個編譯器命令行 arguments 正在定義VERSION
宏,以提供auto
, auto&
或auto const &
。
所以基本上如果向量包含簡單類型(如內置)只需使用auto
,因為它更方便。 在其他復雜類型的情況下,您需要多考慮一下並在auto
和auto&
之間做出決定。 如果有疑問,請進行一些測量或檢查組裝。
在上面的示例中,使用auto const& i
而不是auto i
可能沒有性能劣勢。 在類型是相對較小的類型的情況下,編譯器可能能夠優化引用。
當您編譯這兩個版本時,您可以檢查生成的代碼以查看編譯器是否生成了相同的代碼。 然后你就知道你的編譯器做了什么
另請參閱一個好的 C++ 編譯器會優化參考嗎? .
新的循環樣式看起來很簡單,但有一些陷阱需要避免,比如 C++ 中的所有地方:
您有四種方法來聲明循環變量以供選擇:
auto i
創建項目的可寫副本。 對該項目的寫入會丟失,因為它只是副本而不是原始項目。 永遠避免這個版本!
auto const i
創建只讀副本。 復制復雜類型的成本可能非常高,因此也要避免使用這種類型
auto &i
創建一個可寫引用。 僅當您要修改項目時才使用此版本。
auto const& i
創建對該項目的只讀引用。 未修改項目時始終使用此選項。 這是最常用的形式,請習慣。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.