如何清空使用自定义比较器的std::priority_queue?
如何清空使用自定义比较器的
std::priority_queue? 我根据std::priority_queue的官方文档,编写了带自定义比较器的队列代码,可正常运行:
#include <functional> #include <queue> #include <vector> #include <iostream> #include <utility> auto queue_cmp = [](std::pair<int, double> const& lhs, std::pair<int, double> const& rhs) { return lhs.second > rhs.second; // 自定义排序规则 }; typedef std::priority_queue<std::pair<int, double>, std::vector<std::pair<int, double>>, decltype(queue_cmp)> custom_queue; template<typename T> void print_queue(T q) { // 传值以使用副本打印 int s = 0; while(!q.empty()) { std::pair<int, double> elem = q.top(); std::cout << s << ": " << elem.first << ", " << elem.second << std::endl; q.pop(); s++; } std::cout << '\n'; } int main() { custom_queue q(queue_cmp); for (int n = 10; n < 20; n++) { double val = static_cast <double>(rand())/(static_cast<double>(RAND_MAX)); q.push(std::pair<int, double>(n, val)); } print_queue(q); // q = custom_queue(queue_cmp); // 取消注释后编译报错 }
编译执行结果:
>> g++ -o test test.cpp >> ./test 0: 15, 0.197551 1: 18, 0.277775 2: 16, 0.335223 3: 11, 0.394383 4: 19, 0.55397 5: 17, 0.76823 6: 12, 0.783099 7: 13, 0.79844 8: 10, 0.840188 9: 14, 0.911647
当我取消注释最后一行尝试重置队列时,出现编译错误,原因是lambda闭包类型的拷贝赋值运算符被删除,导致std::priority_queue的移动赋值运算符无法生成:
>> g++ -o test test.cpp test.cpp: In function ‘int main()’: test.cpp:34:31: error: use of deleted function ‘std::priority_queue<std::pair<int, double>, std::vector<std::pair<int, double> >, <lambda(const std::pair<int, double>&, const std::pair<int, double>&)> >& std::priority_queue<std::pair<int, double>, std::vector<std::pair<int, double> >, <lambda(const std::pair<int, double>&, const std::pair<int, double>&)> >::operator=(std::priority_queue<std::pair<int, double>, std::vector<std::pair<int, double> >, <lambda(const std::pair<int, double>&, const std::pair<int, double>&)> >&&)’ 34 | q = custom_queue(queue_cmp); | ^ In file included from /usr/include/c++/12/queue:64, from test.cpp:2: /usr/include/c++/12/bits/stl_queue.h:498:11: note: ‘std::priority_queue<std::pair<int, double>, std::vector<std::pair<int, double> >, <lambda(const std::pair<int, double>&, const std::pair<int, double>&)> >& std::priority_queue<std::pair<int, double>, std::vector<std::pair<int, double> >, <lambda(const std::pair<int, double>&, const std::pair<int, double>&)> >::operator=(std::priority_queue<std::pair<int, double>, std::vector<std::pair<int, double> >, <lambda(const std::pair<int, double>&, const std::pair<int, double>&)> >&&)’ is implicitly deleted because the default definition would be ill-formed: 498 | class priority_queue | ^~~~~~~~~~~~~~ /usr/include/c++/12/bits/stl_queue.h:498:11: error: use of deleted function ‘<lambda(const std::pair<int, double>&, const std::pair<int, double>&)>&<lambda(const std::pair<int, double>&, const std::pair<int, double>&)>::operator=(const<lambda(const std::pair<int, double>&, const std::pair<int, double>&)>&)’ test.cpp:7:19: note: a lambda closure type has a deleted copy assignment operator 7 | auto queue_cmp = [](std::pair<int, double> const& lhs, | ^
我尝试将lambda换成普通函数比较器,问题依然存在:
bool queue_cmp(std::pair<int, double> const& lhs, std::pair<int, double> const& rhs) { return lhs.second > rhs.second; // 自定义排序规则 };
请问这种情况下如何重置队列q?
解决方案
方法1:循环调用pop()清空
最直接的方式,逐个弹出队列元素直到为空:
while (!q.empty()) { q.pop(); }
优点是无需修改原有代码结构,缺点是当队列元素数量极大时,效率略低于直接替换底层容器。
方法2:使用swap()交换空队列
利用std::priority_queue的swap()成员函数,和一个临时空队列交换内部状态。该操作不会触发赋值运算符,因此可以避开lambda的拷贝赋值问题:
q.swap(custom_queue(queue_cmp));
swap()仅交换队列的底层容器和比较器的内部引用,效率极高。
方法3:替换为可拷贝的比较器类型
将lambda或普通函数替换为结构体类型的比较器,这类类型默认支持拷贝和赋值,能让priority_queue的赋值运算符正常工作:
struct QueueCmp { bool operator()(const std::pair<int, double>& lhs, const std::pair<int, double>& rhs) const { return lhs.second > rhs.second; } }; // 重新定义队列类型 typedef std::priority_queue<std::pair<int, double>, std::vector<std::pair<int, double>>, QueueCmp> custom_queue;
此时直接通过赋值空队列即可清空:
q = custom_queue();
内容的提问来源于stack exchange,提问作者fghoussen
相关产品推荐
相关产品推荐

