2011-08-06 86 views
256

用於基於範圍爲C++ 11的常見的例子()環路是總是簡單的東西這樣的:如何使用基於範圍的for()循環與std :: map?

std::vector<int> numbers = { 1, 2, 3, 4, 5, 6, 7 }; 
for (auto xyz : numbers) 
{ 
    std::cout << xyz << std::endl; 
} 

在這種情況下,xyzint。但是,當我們有像地圖一樣的東西時會發生什麼?什麼是變量在這個例子中,類型:

std::map< foo, bar > testing = { /*...blah...*/ }; 
for (auto abc : testing) 
{ 
    std::cout << abc << std::endl;   // ? should this give a foo? a bar? 
    std::cout << abc->first << std::endl; // ? or is abc an iterator? 
} 

當被經過的容器是簡單的東西,它看起來像範圍爲基礎的()循環會給我們每一個項目,而不是一個迭代器。這很好......如果它是迭代器,我們首先要做的第一件事就是解除引用它。

但我很困惑,當涉及到地圖和multimaps等事情時會發生什麼。

(我仍然在G ++ 4.4,而基於範圍的循環是G ++ 4.6+,所以我還沒有嘗試它尚未機會。)

+3

聲明的範圍與標準庫'std :: begin'和'std :: end'函數或同名的成員函數不一樣。 –

+0

xyz是一個可怕的變量名稱恕我直言。它看起來像x乘以y乘以z或某物。或者三個變量中的一個,x,y和z也沒有意義。爲什麼不使用x? – Will

+3

@will在一個3行的例子中,你被抓到了假的變量名? –

回答

359

容器的每個元素都是一個map<K, V>::value_type ,這是的typedef。因此,你可以這樣寫:

for (auto& kv : myMap) { 
    std::cout << kv.first << " has value " << kv.second << std::endl; 
} 

爲了提高效率,最好將循環中的參數作爲參考。如果您需要值的只讀視圖,您也可以考慮製作它const

+54

'auto&kv:myMap'會更好,避免'map <>'中每個值的不必要的副本。 – ildjarn

+55

'auto const&kv'會更好。無論如何。 – Nawaz

+2

@Puppy,你能解釋一下嗎? – Timmmm

24

從本文:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2049.pdf

for(type-specifier-seq simple-declarator : expression) statement

在語法上等同於

{ 
    typedef decltype(expression) C; 
    auto&& rng(expression); 
    for (auto begin(std::For<C>::begin(rng)), end(std::For<C>::end(rng)); begin != end; ++ begin) { 
     type-specifier-seq simple-declarator(*begin); 
     statement 
    } 
} 

所以,你可以清楚地看到,什麼是abc你的情況將是std::pair<key_type, value_type >。 所以打印您可以通過abc.firstabc.second

2

做訪問的每個元素,如果foo和bar的拷貝賦值運算符是便宜(如int,焦炭,指針等),你可以做到以下幾點:

foo f; bar b; 
BOOST_FOREACH(boost::tie(f,b),testing) 
{ 
    cout << "Foo is " << f << " Bar is " << b; 
} 

EDIT:以下不作爲:工作之前,它必須是一個聲明,而不是一個左值表達

foo f;bar b; 
for(std::tie(f,b) : testing) 
{ 
    cout << "Foo is " << f << " Bar is " << b; 
} 
+2

必須有一個聲明,而不是':'左側的表達式。 – aschepler

+4

代碼的第一部分未使用「C++ 11基於範圍的for()」。它不是「C++ 11:如何使用基於範圍的for()循環與std :: map?」的答案。 – isoiphone

+0

反對,因爲這將無法正常工作。根據[n3853](http://open-std.org/JTC1/SC22/WG21/docs/papers/2014/n3853.htm),對於(std :: tie(f,b):testing)'是實際上相當於'for(auto && std :: tie(f,b):testing)',這是不合格的。 – ytj

55

在C++ 17這叫做structured bindings,這允許以下內容:

std::map< foo, bar > testing = { /*...blah...*/ }; 
for (const auto& [ k, v ] : testing) 
{ 
    std::cout << k << "=" << v << "\n"; 
} 
+0

Ist有可能獲得一個'const&'鍵,但是一個非const引用的值? (因爲這就是map :: value_type的作用...) – peterchen

+1

@peterchen:如果使用for(auto&[k,v]:testing),則'k'爲'const' – dalle

+0

關於結構化綁定的cpppreference http:// en .cppreference.com/W/CPP /語言/ structured_binding – TankorSmash