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


...
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((:它们都有相同的方法签名。

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

否。不能在constmap上调用std::map::operator[]。它可能会修改map(如果指定的密钥不存在(。(BTWstd::map::at不会修改map,如果指定的密钥不存在,它会抛出std::out_of_range。(

您可以用mutable标记lambda;否则lambda的operator()是常量限定的,并且通过复制捕获的对象也是const,则不能对其调用operator[]

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

除非在lambda表达式中使用了关键字mutable,否则函数调用运算符是const限定的通过复制捕获的是不可从此CCD_ 13内部修改的。

例如

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 < ?
};

最新更新