类内std::priority_queue自定义比较器的定义规范与实现选型
custom_comparer_t 通用定义规范
std::priority_queue的第三个模板参数要求是满足严格弱序的可调用类型,针对你的场景通用规范如下:
- 可调用对象接收两个
const info&类型的入参,返回值可隐式转换为bool - 若第一个入参的优先级低于第二个入参(应该排在第二个元素后面),返回
true,否则返回false - 必须满足严格弱序要求:非自反性(
comp(a,a) == false)、非对称性(若comp(a,b)==true则comp(b,a)==false)、传递性、等价传递性
注意:
std::priority_queue默认使用std::less<T>,最终堆顶是比较逻辑里的最大元素,和多数人使用大顶堆的直觉一致。
三种实现方案优劣对比
1. info结构体内部重载</>运算符
- 适用场景:
info的排序规则全局唯一,所有用到info排序的场景都用同一套逻辑 - 优势:代码最简洁,不需要额外定义比较器类型,直接用默认的
std::less/std::greater作为模板参数即可 - 劣势:比较逻辑和
info强绑定,后续如果需要不同的排序规则无法复用info结构
2. 独立仿函数(函数对象)
- 适用场景:需要多套排序规则复用、或者比较逻辑需要携带内部状态
- 优势:
- 类型可直接作为模板参数传入队列,不需要在构造时额外传入实例
- 可以和
info解耦,同一个info可搭配多个不同的仿函数实现不同排序逻辑 - 支持携带内部状态,可实现动态调整排序规则的需求
- 针对你的场景,可直接定义为
custom类的私有内嵌类型,不会对外暴露内部实现
- 劣势:需要单独定义结构体,代码量略高于重载运算符
3. Lambda 表达式
- 适用场景:比较逻辑仅在当前
custom类内部使用,是一次性的简单逻辑 - 优势:逻辑写在使用位置附近,可读性高,不需要单独定义额外类型
- 劣势:
- C++11/14 版本中 lambda 类型无法直接作为模板参数,需要用
std::function包装或者用decltype取类型,写法繁琐 - 无法复用,也不适合复杂的比较逻辑
- C++11/14 版本中 lambda 类型无法直接作为模板参数,需要用
最优选择建议
如果你的info排序规则固定,不需要支持多种排序逻辑,优先选择重载比较运算符,代码成本最低;如果需要多套排序规则、或者比较逻辑需要带状态,优先选择独立仿函数;如果只是当前类一次性的简单排序逻辑,也可以选择Lambda 表达式。
内容的提问来源于stack exchange,提问作者roulette01
相关产品推荐
相关产品推荐

