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

使用Lambda作为自定义比较器创建集合时报错:尝试引用已删除函数

错误含义解释

这个报错的核心是:你试图调用一个被编译器删除的函数——也就是你定义的lambda表达式的闭包类型的默认构造函数。

在C11到C17标准中,lambda生成的闭包类型默认没有默认构造函数(C++20开始,无捕获的lambda才允许默认构造,但旧标准不支持)。当你用decltype(comparator)作为set的比较器类型时,这个类型就是lambda的闭包类型,而后续代码中(比如用H[key]访问不存在的键时),unordered_map会尝试默认构造一个set对象,而set的默认构造函数需要默认构造它的比较器——也就是你的lambda闭包,但这个闭包的默认构造函数已经被删除了,所以编译器抛出了这个错误。

你的代码问题

核心问题是:将lambda闭包类型直接作为set的比较器类型,而lambda闭包无法被默认构造,但unordered_map在创建新的set元素时(比如通过operator[])必须调用set的默认构造函数,这就触发了矛盾。

解决方案

最稳妥且简洁的方案是把lambda换成自定义的结构体比较器,这样可以完全避开lambda闭包的构造限制:

// 定义一个带operator()的结构体作为比较器
struct PairComparator {
    bool operator()(const pair<int, int>& a, const pair<int, int>& b) const {
        return a.second == b.second ? a.first < b.first : a.second < b.second;
    }
};

// 直接使用结构体作为set的比较器类型
unordered_map<int, set<pair<int, int>, PairComparator>> H;

这个方案的优势很明显:

  • 结构体的默认构造函数是编译器自动生成的,set可以正常默认构造,unordered_map的operator[]也能正常工作
  • 代码可读性更高,符合C++的常规写法
  • 没有额外的性能开销(不像std::function会有轻微的间接调用开销)

如果你坚持想用lambda,也可以用std::function包装它,但需要注意必须显式初始化每个set的比较器,避免默认构造空的std::function导致运行时崩溃:

#include <functional> // 必须包含这个头文件

using ComparatorFunc = function<bool(const pair<int, int>&, const pair<int, int>&)>;
auto comparator = [](const pair<int, int>& a, const pair<int, int>& b) {
    return a.second == b.second ? a.first < b.first : a.second < b.second;
};

unordered_map<int, set<pair<int, int>, ComparatorFunc>> H;
// 插入元素时必须显式构造带比较器的set
H.emplace(123, set<pair<int, int>, ComparatorFunc>(comparator));

不过这种写法不如结构体方案简洁,还有一定的运行时开销,所以更推荐前者。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 11:02:52