如何使用基于范围的()与std :: map循环?

()循环的C ++ 11基于范围的常见示例总是如此简单:

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

在这种情况下, xyz是一个int 。 但是,当我们有像地图一样的东西时会发生什么? 这个例子中variables的types是什么:

 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+,所以我还没有机会尝试它。)

容器的每个元素都是一个map<K, V>::value_type ,它是std::pair<const K, V>typedef 。 因此,你会写这个

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

为了提高效率,最好将循环中的参数作为参考。 如果你想要一个值的只读视图,你也可以考虑使它成为const

在C ++ 17中,这被称为结构化绑定 ,它允许以下内容:

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

从这篇文章: 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 } } 

所以你可以清楚地看到在你的情况下, abcstd::pair<key_type, value_type > 。 因此,对于打印,您可以通过abc.firstabc.second访问每个元素

如果您只想查看地图中的键/值并使用boost,则可以使用带有基于范围的循环的boost适配器:

 for (const auto& value : myMap | boost::adaptors::map_values) { std::cout << value << std::endl; } 

有一个等效的boost :: adapters :: key_values

http://www.boost.org/doc/libs/1_51_0/libs/range/doc/html/range/reference/adaptors/reference/map_values.html

如果foo和bar的复制赋值操作符便宜(例如int,char,pointer等),则可以执行以下操作:

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

编辑 :下面不像以前一样工作,它必须是一个声明 ,而不是一个左值 expression式

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