You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用自定义类的C++ std::set返回错误lower_bound值问题

问题分析:std::set的lower_bound与upper_bound返回结果不符合预期

问题描述

定义了Tile类,使用自定义比较器tCmp_id的std::set<Tile, tCmp_id>容器存储Tile对象,插入id为1、2、4、5的元素后,调用lower_bound(mkTile(3))和upper_bound(mkTile(3))时,预期分别返回id为2和4的元素,但实际两次输出均为4。

代码如下:

#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
using namespace std;

class Tile {
    public:
        int id;
};
struct tCmp_id {
    bool operator()(Tile a, Tile b) const {
        return a.id < b.id;
    }
};

set<Tile, tCmp_id> TQ;

Tile mkTile(int id){
    Tile t;
    t.id = id;
    return t;
}

int main(){
    TQ.insert(mkTile(1));
    TQ.insert(mkTile(2));
    TQ.insert(mkTile(4));
    TQ.insert(mkTile(5));

    cout << (*TQ.lower_bound(mkTile(3))).id << endl;
    cout << (*TQ.upper_bound(mkTile(3))).id << endl;
}

原因分析

  • API概念理解偏差

    • std::set::lower_bound(k)返回第一个不小于k的元素(基于比较器逻辑)。这里比较器tCmp_id以a.id < b.id作为排序依据,"不小于k"即元素id ≥ 3,集合中第一个满足该条件的是id=4的元素。
    • std::set::upper_bound(k)返回第一个大于k的元素,即元素id > 3,集合中第一个满足该条件的同样是id=4的元素。
    • 你预期lower_bound返回id=2是错误的,id=2是小于3的元素,而lower_bound的设计逻辑不会返回小于目标值的元素。若要获取小于等于3的最后一个元素,需要通过--TQ.upper_bound(mkTile(3))实现。
  • 比较器效率问题(非功能错误)
    比较器的operator()使用了值传递参数(Tile a, Tile b),每次比较都会拷贝Tile对象,虽不影响功能,但建议改为const引用传递(const Tile& a, const Tile& b)以提升运行效率。

修复示例(获取小于等于3的元素)

如果需要得到id=2的元素(即集合中小于等于3的最后一个元素),可修改main函数代码:

int main(){
    TQ.insert(mkTile(1));
    TQ.insert(mkTile(2));
    TQ.insert(mkTile(4));
    TQ.insert(mkTile(5));

    // 获取第一个大于3的元素,向前移动一位得到小于等于3的最后一个元素
    auto upper_iter = TQ.upper_bound(mkTile(3));
    if (upper_iter != TQ.begin()) {
        auto target_iter = prev(upper_iter);
        cout << (*target_iter).id << endl; // 输出2
    }
    cout << (*TQ.upper_bound(mkTile(3))).id << endl; // 输出4
}

内容的提问来源于stack exchange,提问作者codexistent

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 16:45:30