2013-09-27 43 views
9

在C++ 11,如果我使用基於範圍的循環矢量,它會保證迭代順序?說,下面的代碼塊會保證相同的輸出嗎?將範圍基於循環在C++保留索引順序

vector<T> output; 
vector<U> V; 
for(auto v: V) output.push_back(f(v)); 

VS

for(int i =0; i < V.size(); ++i) output.push_back(f(V[i])); 

如果它不是什麼vectormap等?

+0

你當然可以通過執行'auto&'而不是'auto'來優化一些不必要的副本 –

回答

10

是的,這兩個代碼保證做同樣的事情。雖然我沒有鏈接到標準,你可以看看here。我引述如下:You can read that as "for all x in v" going through starting with v.begin() and iterating to v.end().

+0

或[here](http://msdn.microsoft.com/en-us/library/vstudio/jj203382.aspx) 爲表達式中的每個元素重複執行語句**按順序執行**。 – qxixp

10

是的,沒有(這取決於所使用的容器):)

  • 基於該範圍是一個循環像(迭代器POS = range.begin(; POS = !範圍變量= * pos */...}
  • 運算符[]可能會做一些不同的事情(例如,一個std :: map運算符會在密鑰並創建一個新條目,如果密鑰不存在)

例如:

#include <iostream> 
#include <map> 

int main() 
{ 
    typedef std::map<int, int> map; 
    map m = { { 0, 0 }, { 2, 2 }, { 4, 4 } }; 
    for(const auto& e : m) { 
     std::cout << e.first << " "; 
    } 
    std::cout << std::endl; 
    for(map::size_type i = 0; i < m.size(); ++i) { 
     std::cout << m[i] << " "; 
    } 
    std::cout << std::endl; 
    return 0; 
} 

結果是:

0 2 4 
0 0 2 0 4 

(第二個結果可能是在自己的腳好球,甚至預期)

+4

您應該指出,無論是哪種方式,用戶在這個例子中都做了一件很糟糕的事情。如果你在'map'上鍵入'int'的順序索引,那麼你不應該使用'map',你應該使用'deque'或'vector'或'array'。如果你沒有順序索引,那麼你應該使用迭代器進行迭代,而不是使用'for(int i = 0; i OmnipotentEntity

10

是的,他們是等價的。標準保證在6.5.4:

對於範圍爲基礎的形式

爲(對於範圍聲明:表達)的語句語句

設範圍-INIT相當於用括號(表達式)所包圍的表達

和用於基於範圍的形式

爲語句(範圍聲明:支撐-INIT列表)語句

讓range-init等同於braced-init-list。在每種情況下,範圍爲基礎的語句相當於

{ 
    auto && __range = range-init; 
    for (auto __begin = begin-expr, 
     __end = end-expr; 
     __begin != __end; 
     ++__begin) { 
    for-range-declaration = *__begin; 
    statement 
    } 
} 

其中__range,__begin,和__end是變量的論述僅限定,並且_RangeT是表達式的類型,和begin- expr和end-EXPR確定如下:表達式的 ,並開始-expr和end-EXPR如下確定:

- 如果_RangeT是數組類型,開始-expr和end-EXPR是__range和__range + __bound,其中__bound是數組綁定。如果_RangeT是一個未知大小的數組或者一個不完整類型的數組,那麼這個程序是不合格的;

- 如果_RangeT是一個類類型,那麼在類_RangeT 的範圍內查找非限定id開始和結束,就好像通過類成員訪問查找(3.4.5)一樣,並且如果(或兩者)至少一個聲明,begin- expr和end-expr分別是__range.begin()和__range.end(); (其中begin和expr分別是begin(_ 範圍)和end(_range),其中begin和end分別用參數相關查找(3.4.2)進行查找。爲了查找這個名稱,namespace std是一個關聯的名稱空間。

雖然你對地圖的問題有點無意義。如果它是有序地圖,並且正確地遍歷地圖,則它們是等效的。如果它是一個無序的映射,那麼你的問題沒有多大意義。