2016-02-15 80 views
6

給定一個向量,vc,一個可以通過向量與一系列迭代爲:應該使用循環的範圍而不是矢量上的迭代器?

for (auto c : vc) 
    std::cout << c; 

或用一個迭代:

for (auto it = vc.cbegin(); it != vc.cend(); ++it) 
    std::cout << *it; 

有一種使用一個方法比其他的功能性理由,或者這只是一個風格問題?

+4

請注意,如果您在基於範圍的for循環中使用'auto',則會獲得矢量元素的*副本,如果您的對象複製開銷很大,則可能會產生不必要的性能問題。通過使用迭代器,你可以得到一個const引用,所以副本不會在這裏發生。在基於範圍的for中找回const引用的方法是for(const auto&c:vc)...' –

回答

4

從性能的角度來看,沒有什麼區別。正如Bjarne Stroustrup在他的書中寫的第4版C++編程語言:

最簡單的循環是一個範圍 - 表達式;它只是讓程序員訪問一個範圍的每個元素 。

作爲KISS原則的愛好者,我傾向於更簡單的構造而不是更復雜的構造。但是,它真的歸結爲你想要達到的目標。從同一本書Bjarne揭示了爲什麼範圍-for循環被設計爲簡單:

請注意,範圍for循環是一個故意簡單的構造。對於 示例,使用它您不能同時觸摸兩個元素,並且 不能同時有效地遍歷兩個範圍。爲此,我們需要 一般性的陳述。

因此,有不能使用的範圍,for循環的上下文,你必須駐留在古典的語句。

底線使用range-for循環時,因爲更簡單和更具可讀性。

4

這或多或少都是風格問題,但可以這樣考慮; range-for循環比顯式迭代器使用更簡潔。你寫的代碼越少,出現問題的地方就越少。

+1

此外,它更加可讀,因爲它隱藏了循環的實現細節。 – emlai

+1

範圍可能對編譯器更清晰,提高優化性。 – alcedine

+0

好點。我同意。 – JesseTG

2

對於您的具體示例,它們是等效的。而且由於它們是等價的,所以你自然希望更傾向於最短的版本,而這個版本也是最不容易出錯的 - 免費的。

範圍-for循環還建議被進一步簡化爲:

for (var : range) 

其中var將具有類型auto&&(又名forwading /通用參考),它是採取以一個基準的最佳方式目的。只需auto var將製作每個元素的副本,這可能並不便宜。不幸的是,它沒有通過。

您通常不直接使用迭代器,因此範圍 - 您應該是您的第一選擇。顯式迭代器也可能指向超出範圍的元素,因爲您可以在範圍內自由移動,導致未定義的行爲。

1

你的兩個例子有兩個實質性的區別。首先,auto c會創建每個元素的副本,因此如果您不想創建不必要的副本,請使用auto const& c。其次,範圍for以非常量迭代器的形式實現,但您的for循環使用常量迭代器。如果vc是標準容器,那麼這並不重要,但是一些容器(例如Qt中的那些容器)使用內部共享指針實現了寫時複製語義,在這種情況下,使用非const迭代器將不必要地複製整個容器。你能避免這一點,仍然可以使用C++ 17 std::as_const用好的範圍for語法:

for (auto const& c : std::as_const(vc)) 
    std::cout << c; 

您可以輕鬆地實現自己的as_const版本,如果你的環境沒有提供它。