如何修正priority_queue比较函数?解决unordered_map限定符丢弃编译报错
修复"传递unordered_map作为‘this’参数会丢弃限定符"的错误
嘿,这个错误我之前也踩过坑,核心问题出在你的lambda表达式和unordered_map的成员函数限定符冲突上,我给你拆解清楚,再给几个靠谱的修复方案:
错误原因到底是什么?
- 你写的lambda
byCount默认是const属性的(没加mutable的话,lambda内部的捕获变量都是const的),而你按值捕获了counts,所以在lambda里counts是个const版本的unordered_map。 - 你用
counts[a]来获取次数,但unordered_map的operator[]是个非const成员函数——因为如果key不存在,它会自动插入这个key并赋值0,这会修改map,所以const对象根本不能调用它。 - 这就导致编译器报错:你试图把const的map当成非const的来用,"丢弃了限定符"。
方案1:用at()替代operator[](最推荐)
既然我们已经遍历过nums统计了所有元素的次数,优先队列里的元素都是counts里已有的key,完全可以用安全的const成员函数来获取次数:
void sortByFreq(const vector<int>& nums) { unordered_map<int, int> counts; for (auto i: nums) ++counts[i]; // 改成const引用捕获,避免拷贝整个map,性能更好 auto byCount = [&counts](const int& a, const int& b) { // 因为a和b都是counts里的key,直接用at()安全又高效 return counts.at(a) > counts.at(b); }; priority_queue<int, vector<int>, decltype(byCount)> minFreq(byCount); for (auto& kv: counts) { minFreq.push(kv.first); } // ... 你的后续逻辑 }
这里用counts.at(a)代替counts[a],at()是const成员函数,允许在const上下文中调用,而且如果key不存在会抛异常(但我们这里不会出现这种情况,因为push的都是counts里的key),比operator[]更安全。另外把值捕获改成&counts的引用捕获,避免不必要的map拷贝,提升性能。
方案2:给lambda加mutable(不推荐,除非特殊需求)
如果你非要用operator[](其实完全没必要),可以给lambda加上mutable,这样lambda内部的捕获变量就不是const的了:
auto byCount = [counts](const int& a, const int& b) mutable { return counts[a] > counts[b]; };
但这个方案有两个坑:一是会拷贝整个counts map,性能差;二是如果不小心访问了不存在的key,会修改拷贝后的map,导致统计结果出错,所以尽量别用。
方案3:换个思路,用vector排序替代优先队列
如果你的场景不需要优先队列的特性,其实可以把键值对转成vector直接排序,代码更简洁:
void sortByFreq(const vector<int>& nums) { unordered_map<int, int> counts; for (auto i: nums) ++counts[i]; // 把counts的键值对转成vector vector<pair<int, int>> freq_list(counts.begin(), counts.end()); // 按频率降序排序(要升序就改成p1.second < p2.second) sort(freq_list.begin(), freq_list.end(), [](const auto& p1, const auto& p2) { return p1.second > p2.second; }); // 之后遍历freq_list就能拿到按频率排序的元素了 // ... }
这种方式避开了优先队列和lambda的const问题,代码可读性也更高,适合大多数情况。
内容的提问来源于stack exchange,提问作者grokus
相关产品推荐
相关产品推荐

