0
...
        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() :两者都具有相同的方法签名。

4

2 回答 2

3

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

std::map::operator[]不可以const map。_ 它可能会修改map(如果指定的键不存在)。(顺便说一句std::map::at,不会修改,如果指定的键不存在map,它会抛出。)std::out_of_range

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

mutable : 允许 body 修改由 copy 捕获的对象,并调用它们的非常量成员函数

除非在 lambda 表达式中使用了关键字 mutable,否则函数调用运算符是 const 限定的,并且由 copy 捕获的对象在 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作为变量将是一个好主意。

于 2020-05-06T01:58:57.820 回答
2

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

此外,您是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 < ?
};
于 2020-05-06T02:14:26.443 回答