我可以使用基于范围的 for 循环轻松迭代地图的值吗?

Posted

技术标签:

【中文标题】我可以使用基于范围的 for 循环轻松迭代地图的值吗?【英文标题】:Can I easily iterate over the values of a map using a range-based for loop? 【发布时间】:2012-10-16 17:24:11 【问题描述】:

是否可以仅使用“foreach”来迭代 std::map 中的所有值?

这是我当前的代码:

std::map<float, MyClass*> foo ;

for (map<float, MyClass*>::iterator i = foo.begin() ; i != foo.end() ; i ++ ) 
    MyClass *j = i->second ;
    j->bar() ;

有没有办法可以做到以下几点?

for (MyClass* i : /*magic here?*/) 
    i->bar() ;

【问题讨论】:

为什么你不喜欢 i->second->bar() ? 看看[这个问题的答案][1]。我认为这正是你所需要的。 [1]:***.com/questions/6963894/… @LyubomirVasilev:不,那只是询问如何在一般地图上迭代范围。这个问题询问如何仅对值进行专门迭代。 @Xeo 啊,我明白了。我忽略了这一点。 【参考方案1】:

由于C++20,您可以将范围适配器std::views::values 从Ranges library 添加到您的range-based for loop。这样您就可以实现与Xeo's answer 中的解决方案类似的解决方案,但无需使用 Boost:

#include <map>
#include <ranges>

std::map<float, MyClass*> foo;

for (auto const &i : foo | std::views::values)
    i->bar();

Code on Wandbox

【讨论】:

【参考方案2】:

C++1z/17 开始,您可以使用结构化绑定

#include <iostream>
#include <map>
#include <string>

int main() 
   std::map<int, std::string> m;

   m[1] = "first";
   m[2] = "second";
   m[3] = "third";

   for (const auto & [key, value] : m)
      std::cout << value << std::endl;

【讨论】:

结构化绑定很棒,但我编译时使用 -Werror 和未使用的变量,因为密钥没有被大量使用 :) 试试[[maybe_unused]]属性。见这里***.com/q/41404001/580083 @galois 和 @Daniel,对不起,如果这是一个基本问题,那么 Structured Bindings 到底是什么?提前非常感谢! @Milan 你试过用谷歌搜索吗?周围有很多解释。 @DanielLangr 我正在阅读一个答案,当我读到一个新单词时,我就在这里发表了评论。但你是对的......我应该先用谷歌搜索它。对于那个很抱歉。 (对于未来的读者:我发现这个关于 Structured Bindings 的简短视频非常有用:youtu.be/eUsTO5BO3WI)【参考方案3】:
std::map<float, MyClass*> foo;

for (const auto& any : foo) 
    MyClass *j = any.second;
    j->bar();

在 c++11(也称为 c++0x)中,您可以像在 C# 和 Java 中一样进行此操作

【讨论】:

“你能做到”是什么意思?您是指一般的基于范围的 for 循环吗? 是的!新的 C++ 标准 c++11 引入了新的 for-range 语法特性,更容易在容器中迭代元素。例如:vector vec0, 1, 2 ,3, 4, 5, 6, 7, 8, 9;现在在 c++11 中,您可以编写如下代码:for(auto any : vec) cout 嗯……这不是很有帮助,因为我在发布之前就知道基于范围的循环……我的问题,@Xeo 已经回答了,是关于如何仅遍历地图的值,没有像MyClass *j = any.second ; 这样的行:P 我理解 auto,但为什么要使用 const auto&?循环中不能编辑变量吗?【参考方案4】:

神奇在于Boost.Range's map_values adaptor:

#include <boost/range/adaptor/map.hpp>

for(auto&& i : foo | boost::adaptors::map_values)
  i->bar();

它被正式称为“基于范围的 for 循环”,而不是“foreach 循环”。 :)

【讨论】:

我会写auto const&amp;&amp; @Cheersandhth.-Alf 我想你的意思是auto const &amp;&amp;i :) @Xeo /基于范围的for循环/。我知道。我一定是看 SO 标签太久了…… 6_9 无论如何,谢谢!这正是我一直在寻找的。你能解释一下为什么那里的管道是有效的吗?那是按位or,对吧? @Blacklight:Boost.Range 的适配器使operator| 过载,以使链接更容易:map | map_values | filtered(pred) | transformed(blub) | reversed。 :) @Blacklight: It's all there in the documentation! :)

以上是关于我可以使用基于范围的 for 循环轻松迭代地图的值吗?的主要内容,如果未能解决你的问题,请参考以下文章

C++基于范围的for循环详解

C++11 反向基于范围的 for 循环

C++11 反向基于范围的 for 循环

转到基于范围的 for 循环中的下一个迭代器

基于范围的 for 循环与常规迭代器 for 循环

C++范围for