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
How to use range-based for() loop with std::map?
提问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 xyz
is 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 typedef
for std::pair<const K, V>
. Consequently, in C++17 or higher, you can write
容器的每个元素都是一个map<K, V>::value_type
,也就是一个typedef
for 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 for
loops 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 kv
variable const
if 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 abc
in your case will be std::pair<key_type, value_type >
.
So for printing you can do access each element by abc.first
and 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
回答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;
}