[英]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() 循环会给我们每个项目,而不是迭代器。 这很好……如果它是迭代器,我们总是要做的第一件事就是取消引用它。
但是当涉及到地图和多地图之类的东西时,我对期望什么感到困惑。
(我仍然使用 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::adaptors::key_values
如果 foo 和 bar 的复制赋值运算符很便宜(例如 int、char、pointer 等),您可以执行以下操作:
foo f; bar b;
BOOST_FOREACH(boost::tie(f,b),testing)
{
cout << "Foo is " << f << " Bar is " << b;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.