如何在std::map的值上使用基于范围的for循环

How do you use a range-based for loop on the values of a std::map?

本文关键字:于范围 循环 范围 for std map      更新时间:2023-10-16

我正试图使用std::map::operator[]来迭代具有基于范围的for循环的std::map的值,但以下内容无法编译:

#include <iostream> // cout, endl
#include <map>      // map
#include <set>      // set
using namespace std;
int main () {
    using namespace std;
    const map<int, set<int>> m {{2, {201, 202}}, {3, {301, 302}}};
    for (int v : m[2])
        cout << v << endl;
    return 0;
 }

这是编译器的错误消息:

Test.c++:18:19: error: no viable overloaded operator[] for type 'const map<int, set<int> >'
    for (int v : m[2])

接下来的问题是,既然at()有两个版本,为什么没有[]的两个版本?

map::operator[]在未找到键的情况下将新元素插入映射中,因此它不能是const,也不能在const map上调用。

请改用m.at(2)

operator[]将执行两件事中的一件。如果元素存在,它会在该位置找到元素并返回。如果该位置没有元素,它会对其进行值初始化,然后返回。

因此,它既不是逻辑上的,也不是程序上的const

虽然您可能会说"但是有一个元素2",但操作的const程度仅取决于参数的类型,而不是参数的值。并且m[int]不能保证在那里有一个有效的元素。

要解决此问题,可以将m[2]替换为m.find(2)->second。如果映射中缺少2,则执行未定义的行为,但如果存在2,则其计算结果与m[2]相同。相反,如果2作为密钥存在,m.at(2)将再次执行相同的操作,如果不存在,则抛出异常。

顺便说一句,当处理这样的问题时,试着把代码分解成更小的部分。m[2];本身在一行上将无法编译。事实上,错误消息告诉你它找不到operator[]——这可能会给你一个错误的线索。

您的映射m被声明为const,这意味着您只能在其上调用const函数。

std:map::operator[]不是这样的函数,因为如果找不到指定的键,它将修改映射。

你需要的是std::map::at,也就是const,所以你可以在你的const地图上称它。