如何使用基于范围的 for 循环修改地图中的值?

Posted

技术标签:

【中文标题】如何使用基于范围的 for 循环修改地图中的值?【英文标题】:How can I modify values in a map using range based for loop? 【发布时间】:2015-10-26 00:30:48 【问题描述】:

我有一个基于范围的 for 循环来遍历 foobar 中的元素,如下所示:

#include <map>
#include <iostream>

int main()

  std::map<int, int> foobar(1,1, 2,2, 3,3);

  for(auto p : foobar) 
  
    ++p.second;
    std::cout << "" << p.first << ", " << p.second << " ";
  
  std::cout << std::endl;

  for(auto q : foobar) 
  
    std::cout << "" << q.first << ", " << q.second << " ";
   
  std::cout << std::endl;

此代码产生以下输出:

1, 2 2, 3 3, 4
1, 1 2, 2 3, 3

第一行在 for 循环中被修改和打印,第二行应该打印相同的修改值。为什么输出不匹配?对std::map 的更改是否仅在循环范围内有效?有没有办法我不仅可以访问而且可以修改这些值?

running version of this code 可以在 cpp.sh 上找到。

编辑:为了清楚起见,修改了此处给出的示例以匹配接受的答案。

【问题讨论】:

【参考方案1】:

如果你想改变/修改容器,你可以把auto变成auto&amp;,例如:

#include <map>
#include <iostream>

int main()

  std::map<int, int> foobar(1,1, 2,2, 3,3);
  for(auto& p : foobar) 
    ++p.second;
    std::cout << '' << p.first << ", " << p.second << " ";
  
  std::cout << std::endl;

编译并输出

1, 2 2, 3 3, 4

live example

【讨论】:

【参考方案2】:

Plain auto 是按价值计算的(你会得到一份副本)。使用auto&amp;

【讨论】:

【参考方案3】:

请注意,从 C++17 开始,您可以使用 结构化绑定

for (auto & [key, value] : foobar)
  std::cout << "" << key << ", " << ++value << " ";

我喜欢这种机制,因为 keyvalue 对于地图的可读性比 p.firstp.second 的可读性强。

【讨论】:

【参考方案4】:

使用auto 关键字将每个值的副本发送到循环中。如果你想改变地图中的原始值,你需要使用auto&amp;

【讨论】:

“当使用for(auto val : myMap)val.second 执行的操作是只读的。” 这不是真的。 ​​​​​​​​​​​您“允许”修改这些值。只是在您的原始代码中,您改为修改 一些其他值(原始值的副本)。没有什么是“只读的”。你看到其他答案了吗?

以上是关于如何使用基于范围的 for 循环修改地图中的值?的主要内容,如果未能解决你的问题,请参考以下文章

为啥基于范围的 for 循环不修改容器元素?

C++11使用auto关键字进行基于范围的for循环,引用符号&的作用

在普通 for 循环中更改 QVector 的对象

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

如何在 std::map 中使用基于范围的 for() 循环?

如何在 std::map 中使用基于范围的 for() 循环?