带成员变量的priority_queue自定义仿函数比较器行为是否未定义?
问题分析
你给出的这段代码确实存在未定义行为,核心原因和解释如下:
1. 比较器实例的来源
std::priority_queue 内部会持有一个独立的比较器实例,你调用默认构造函数初始化队列时:
std::priority_queue<test, std::vector<test>, test> pq;
队列会默认构造一个test类型的实例作为内部专用的比较器,和你后续存入队列的test类型元素完全无关。你在operator()中访问的flag,就是这个内部比较器实例的成员变量,不是队列元素的flag。
2. 未定义行为的触发点
你的test类没有自定义默认构造函数,编译器自动生成的默认构造函数不会初始化内置类型的成员变量,因此内部比较器的flag是未初始化的不确定值。你在operator()中读取这个未初始化的bool变量,本身就属于标准明确规定的未定义行为。
另外你原有代码中重载的operator()没有返回值,违反了比较器必须返回bool类型的要求,这也会触发未定义行为。
正确写法参考
如果你需要自定义比较器的flag值,需要显式构造比较器实例传给队列的构造函数,确保flag被正确初始化:
struct test { bool operator()(const test &lhs, const test &rhs) const { if(flag) { // do stuff } return false; // 按需修改实际比较逻辑的返回值 } bool flag; }; // 显式初始化比较器的flag test comp{true}; // 把比较器实例传给队列构造函数 std::priority_queue<test, std::vector<test>, test> pq(comp);
额外注意:标准库要求关联容器、堆容器的比较器在整个容器生命周期内必须保持严格弱序的规则不变,如果运行中修改比较器内部状态导致比较逻辑变化,后续的容器操作也会触发未定义行为。
内容的提问来源于stack exchange,提问作者roulette01
相关产品推荐
相关产品推荐

