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

C++中从指针类型set中erase元素无效?求解决方法

问题分析与解决

为什么erase(n1)没有生效?

问题出在你自定义的比较器comp上:

  • C++的std::set要求比较函数必须满足严格弱序(Strict Weak Ordering),核心规则包括:对于任意元素x,comp(x, x)必须返回false(反自反性);如果comp(a,b)为true,comp(b,a)必须为false(非对称性)。
  • 你写的return a->val <= b->val违反了反自反性:当a和b指向同一个节点时,a->val <= b->val返回true,这会让set的内部逻辑彻底混乱——它无法正确判断元素是否相等,也无法准确定位要删除的元素。
  • 所以当你调用s.erase(n1)时,set根本找不到n1对应的位置,删除操作实际没执行,集合里的n1依然存在,打印的第二个1其实是n3的val,看起来像是没删掉,本质是删除失败。

正确的解决方法

根据你的需求,分两种情况处理:

情况1:需要按val去重(相同val的节点只存一个)

修改比较器为严格小于<,满足严格弱序:

struct comp{
    bool operator()(const Node* a, const Node* b) const{
        return a->val < b->val; // 改成严格小于
    }
};

此时set会自动去重,插入n3时因为它的val和n1相同,会被视为重复元素而无法插入,集合最终只有n1和n2,调用s.erase(n1)就能正常删除。

情况2:允许存储相同val的不同指针(需要保留n1、n3两个节点)

比较器需要先按val排序,val相同时比较指针本身的地址,确保每个不同的指针都是唯一元素:

struct comp{
    bool operator()(const Node* a, const Node* b) const{
        if(a->val != b->val){
            return a->val < b->val;
        }
        // val相同时,比较指针地址,保证严格弱序
        return a < b;
    }
};

这样set能正确区分n1和n3,调用s.erase(n1)时,set可以通过比较器准确定位到n1,完成删除操作,删除后打印结果会是1,2,。

另外,注意使用完set后要手动释放节点内存,避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 11:02:24