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

Sté*_*ane 316 c++ dictionary for-loop c++11

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

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

在这种情况下xyz是一个int.但是,当我们有像地图这样的东西时会发生什么?此示例中变量的类型是什么:

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?
}
Run Code Online (Sandbox Code Playgroud)

当遍历的容器很简单时,看起来基于范围的()循环将给我们每个项目,而不是迭代器.哪个好...如果它是迭代器,我们总是要做的第一件事就是取消引用它.

但是,当涉及到地图和多重映射等内容时,我会感到困惑.

(我仍然使用g ++ 4.4,而基于范围的循环是g ++ 4.6+,所以我还没有机会尝试它.)

tem*_*def 459

容器的每个元素都是a map<K, V>::value_type,typedef用于std::pair<const K, V>.因此,你写这个

for (auto& [key, value]: myMap) {
    std::cout << key << " has value " << value << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

为了提高效率,最好将循环中的参数作为参考.for如果您想要一个只读的值视图,您也可以考虑制作它.

从C++ 17开始,您也可以编写

for (const auto& [key, value]: myMap) {
    std::cout << key << " has value " << value << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

哪个更清洁.


dal*_*lle 92

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

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

  • @peterchen:如果使用`for(auto&[k,v]:testing)`,`k`是`const` (2认同)
  • 关于结构化绑定的 cpppreference http://en.cppreference.com/w/cpp/language/structured_binding (2认同)

A. *_* K. 25

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

for( type-speci?er-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-speci?er-seq simple-declarator(*begin);
        statement
    }
}
Run Code Online (Sandbox Code Playgroud)

所以你可以清楚地看到abc你的情况会是什么std::pair<key_type, value_type >.因此,对于打印,您可以通过abc.first和访问每个元素abc.second


小智 14

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

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

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

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