C++ 如何在 std::map 中使用基于范围的 for() 循环?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6963894/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 21:02:35  来源:igfitidea点击:

How to use range-based for() loop with std::map?

c++c++11for-loopdictionary

提问by Stéphane

The common example for C++11 range-based for() loops is always something simple like this:

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

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

In which case xyzis an int. But, what happens when we have something like a map? What is the type of the variable in this example:

在这种情况下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?
}

When the container being traversed is something simple, it looks like range-based for() loops will give us each item, not an iterator. Which is nice...if it was iterator, first thing we'd always have to do is to dereference it anyway.

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

But I'm confused as to what to expect when it comes to things like maps and multimaps.

但是当涉及到地图和多地图之类的东西时,我对期望什么感到困惑。

(I'm still on g++ 4.4, while range-based loops are in g++ 4.6+, so I haven't had the chance to try it yet.)

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

回答by templatetypedef

Each element of the container is a map<K, V>::value_type, which is a typedeffor std::pair<const K, V>. Consequently, in C++17 or higher, you can write

容器的每个元素都是一个map<K, V>::value_type,也就是一个typedeffor std::pair<const K, V>。因此,在 C++17 或更高版本中,您可以编写

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

or as

或作为

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

if you don't plan on modifying the values.

如果您不打算修改这些值。

In C++11 and C++14, you can use enhanced forloops to extract out each pair on its own, then manually extract the keys and values:

在 C++11 和 C++14 中,您可以使用增强for循环来单独提取每一对,然后手动提取键和值:

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

You could also consider marking the kvvariable constif you want a read-only view of the values.

如果您想要值的只读视图,您还可以考虑标记kv变量const

回答by dalle

In C++17 this is called structured bindings, which allows for the following:

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

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

回答by A. K.

From this paper: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2049.pdf

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

for( type-speci?er-seq simple-declarator : expression ) statement

for( type-speci?er-seq simple-declarator : expression ) statement

is syntactically equivalent to

在语法上等价于

{
    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
    }
}

So you can clearly see that what is abcin your case will be std::pair<key_type, value_type >. So for printing you can do access each element by abc.firstand abc.second

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

回答by Pixie-Poop

If you only want to see the keys/values from your map and like using boost, you can use the boost adaptors with the range based loops:

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

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

there is an equivalent boost::adaptors::key_values

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

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

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

回答by balki

If copy assignment operator of foo and bar is cheap (eg. int, char, pointer etc), you can do the following:

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

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