如何在std::map中使用基于范围的for()循环
How to use range-based for() loop with std::map?
c++ 11基于范围的for()循环的常见示例总是像这样简单:
std::vector<int> numbers = { 1, 2, 3, 4, 5, 6, 7 };
for ( auto xyz : numbers )
{
std::cout << xyz << std::endl;
}
,此时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?
}
当遍历的容器很简单时,看起来基于范围的for()循环将给出每个元素,而不是迭代器。这很好……如果它是迭代器,那么无论如何我们要做的第一件事就是对它解引用。
但是当涉及到地图和multimaps之类的东西时,我很困惑该期待什么。
(我还在g++ 4.4,而基于范围的循环在g++ 4.6+,所以我还没有机会尝试它。)
容器的每个元素都是一个map<K, V>::value_type
,对于std::pair<const K, V>
是一个typedef
。因此,在c++ 17或更高版本中,可以编写
for (auto& [key, value]: myMap) {
std::cout << key << " has value " << value << std::endl;
}
或
for (const auto& [key, value]: myMap) {
std::cout << key << " has value " << value << std::endl;
}
如果你不打算修改这些值。
在c++ 11和c++ 14中,您可以使用增强的for
循环来单独提取每个对,然后手动提取键和值:
for (const auto& kv : myMap) {
std::cout << kv.first << " has value " << kv.second << std::endl;
}
如果您想要值的只读视图,您也可以考虑将kv
变量标记为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
}
}
所以你可以清楚地看到,在你的情况下,abc
将是std::pair<key_type, value_type >
。对于打印你可以通过abc.first
和abc.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,指针等),您可以执行以下操作:
foo f; bar b;
BOOST_FOREACH(boost::tie(f,b),testing)
{
cout << "Foo is " << f << " Bar is " << b;
}
- 在基于范围的for循环中使用结构化绑定声明
- 为什么 const std::p air<K,V>& 在 std::map 上基于范围的 for 循环不起作用?
- 为什么基于循环范围不直接在C 中使用参数阵列
- 为什么这个循环变量在循环范围之外是可访问的
- 在基于范围的循环范围内的双/整数使用和数据缩小
- 是cbegin/Cend不足以使循环范围
- 变量循环范围会导致返回局部变量的地址引用
- 地图元素上的循环范围
- 使用基于自动的范围用于循环VS,使用对循环范围的基于对的范围
- 访问 C++ 中 if 循环范围之外的矢量
- 循环范围内的初始值设定项列表
- 用于循环范围范围
- 为什么需要两个循环范围来更改C++向量的这些元素
- 在下一个循环之前访问基于 for 循环范围的下一个元素
- 在循环范围之外声明参数是否更有效?
- 循环范围拆分中的变量预评估
- 为什么我的循环范围不会改变元素?
- 我的循环范围不起作用
- 循环范围在使用索引元素时不起作用
- 对基于循环范围的误解