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+中,所以我还没有机会尝试过。)
#1 楼
容器的每个元素都是map<K, V>::value_type
,它是typedef
的std::pair<const K, V>
。因此,在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
。#2 楼
在C ++ 17中,这称为结构化绑定,它允许以下操作:std::map< foo, bar > testing = { /*...blah...*/ };
for ( const auto& [ k, v ] : testing )
{
std::cout << k << "=" << v << "\n";
}
评论
是否有可能获得const&键,但非常量引用值? (因为那就是map :: value_type的功能...)
–peterchen
17年11月8日在17:03
@peterchen:如果用于(auto&[k,v]:testing),则k为常数
– dalle
17年11月14日在9:18
关于结构化绑定的cpppreference en.cppreference.com/w/cpp/language/structured_binding
–TankorSmash
17年12月14日下午3:06
如果使用GCC进行编译,则需要版本7或更高版本的结构化绑定:gcc.gnu.org/projects/cxx-status.html
–csknk
18年7月15日在12:33
#3 楼
摘自本文:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2049.pdffor( 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
访问每个元素#4 楼
如果您只想从地图上查看键/值并且喜欢使用boost,则可以将boost适配器与基于范围的循环配合使用:for (const auto& value : myMap | boost::adaptors::map_values)
{
std::cout << value << std::endl;
}
有一个等效的boost :: adaptors :: key_values
http://www.boost.org/doc/libs/1_51_0/libs/range/doc/html/range/reference/adaptors/reference/map_values。 html
#5 楼
如果foo和bar的复制赋值运算符比较便宜(例如int,char,指针等),则可以执行以下操作:foo f; bar b;
BOOST_FOREACH(boost::tie(f,b),testing)
{
cout << "Foo is " << f << " Bar is " << b;
}
评论
第一个代码段未使用“基于C ++ 11范围的for()”。这不是对“ C ++ 11:如何将基于范围的for()循环与std :: map一起使用?”的答案。
–isoiphone
2014年2月1日下午4:54
@ytj答案中已经提到它不起作用。我不想删除它,以便新用户不必尝试它并再次发现事实。
– Balki
2014年7月3日15:11
评论
statement的范围与标准库std :: begin和std :: end函数或同名成员函数进行了邪恶的冲突。@will在3行示例中,您会发现虚假的变量名吗?