在 lambda 函数中访问周围变量时出错

error in accessing surrounding variable in lambda function

...
        unordered_map<string ,int> map;
        for (const auto& str : words) {
            map[str]++;
        }
        auto cmp = [map](string s1, string s2){
            if (map[s1] == map[s2])
                return s1 < s2;
            return map[s1] > map[s2];
        };
...

这个给我no viable overloaded operator[] for type 'const unordered_map<std::__cxx11::string, int>' (aka 'const unordered_map<basic_string<char>, int>')

但是如果我不使用 [] 运算符而是使用 .at() 进行访问。代码编译。

我不知道为什么。我检查了 [] 运算符和 .at() :两者都具有相同的方法签名。

I check out [] operator and .at() : both have the same method signature.

没有。 std::map::operator[] can't be called on const map. It might modify the map (if specified key doesn't exist). (BTW std::map::at 不会修改 map,如果指定的键不存在,它会抛出 std::out_of_range。)

你可以用 mutable 标记 lambda;否则 lambda 的 operator() 是 const-qualified 并且通过复制捕获的对象也是 const,那么你不能在它上面调用 operator[]

mutable: allows body to modify the objects captured by copy, and to call their non-const member functions

Unless the keyword mutable was used in the lambda-expression, the function-call operator is const-qualified and the objects that were captured by copy are non-modifiable from inside this operator().

例如

auto cmp = [map](string s1, string s2) mutable {
    if (map[s1] == map[s2])
        return s1 < s2;
    return map[s1] > map[s2];
};

PS: 不对变量使用名称 map 是个好主意。

lambda 中捕获的变量默认为 const,除非您将 lambda 标记为 mutableunordered_map 没有可以在 const unordered_map 对象上调用的 operator[],因为如果请求,它会插入(即 修改 )一个新元素找不到密钥。

此外,您正在 map 按值 捕获它,您应该改为 按引用 捕获它(除非您期望cmp 活得比 map)。

试试这个:

unordered_map<string, int> word_counts;

for (const auto& str : words) {
    word_counts[str]++;
}

auto cmp = [&word_counts](const string &word1, const string &word2){
    auto iter = word_counts.find(word1);
    int count1 = (iter != word_counts.end()) ? iter->second : 0;
    iter = word_counts.find(word2);
    int count2 = (iter != word_counts.end()) ? iter->second : 0;
    /* or, throw an exception if word1 or word2 are not found...
    int count1 = word_counts.at(word1);
    int count2 = word_counts.at(word2);
    */
    if (count1 == count2)
        return word1 < word2;
    return count1 > count2; // <-- why > and not < ?
};