在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]));
如果它不是什麼vector
但map
等?
在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]));
如果它不是什麼vector
但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
(第二個結果可能是在自己的腳好球,甚至預期)
您應該指出,無論是哪種方式,用戶在這個例子中都做了一件很糟糕的事情。如果你在'map'上鍵入'int'的順序索引,那麼你不應該使用'map',你應該使用'deque'或'vector'或'array'。如果你沒有順序索引,那麼你應該使用迭代器進行迭代,而不是使用'for(int i = 0; i
是的,他們是等價的。標準保證在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是一個關聯的名稱空間。
雖然你對地圖的問題有點無意義。如果它是有序地圖,並且正確地遍歷地圖,則它們是等效的。如果它是一個無序的映射,那麼你的問題沒有多大意義。
你當然可以通過執行'auto&'而不是'auto'來優化一些不必要的副本 –