贝利信息

c++中functor仿函数是什么_c++函数对象用法【进阶】

日期:2026-01-26 00:00 / 作者:冰火之心
functor 是重载了 operator() 的类,可像函数一样调用且带有状态;如 Adder(5)(10) 返回 15,它非函数指针也非 lambda,但支持内联优化与模板推导,适用于需携带不变数据的泛型场景。

functor 是什么:它就是一个重载了 operator() 的类

在 C++ 里,functor 不是语言关键字,也不是标准库类型,而是一种惯用法:只要一个类定义了 operator() 成员函数,它就能像函数一样被调用。比如:

struct Adder {
    int offset;
    Adder(int o) : offset(o) {}
    int operator()(int x) const { return x + offset; }
};

Adder add5(5);
int result = add5(10); // 等价于 add5.operator()(10),返回 15

关键点在于:它不是函数指针,也不是 lambda(虽然 lambda 编译后也生成 functor),而是有状态、可定制、能内联的类实例。你传的是对象,不是地址,所以编译器更容易优化。

为什么不用普通函数或 lambda:状态和模板推导需求

当需要携带数据(如阈值、权重、缓存)且该数据在调用间保持不变时,functor 比捕获 lambda 更可控——尤其在泛型上下文中。比如 std::sort 接收比较器:

struct CaseIn

sensitiveCompare { bool operator()(const std::string& a, const std::string& b) const { return std::lexicographical_compare( a.begin(), a.end(), b.begin(), b.end(), [](char x, char y) { return std::tolower(x) < std::tolower(y); } ); } }; std::vector v = {"Zoo", "apple", "Banana"}; std::sort(v.begin(), v.end(), CaseInsensitiveCompare{});

这里不能直接用带捕获的 lambda(如 [&](...){...})传给模板函数,因为闭包类型无法显式写出;而无捕获 lambda 虽可退化为函数指针,但失去状态能力。functor 显式、可命名、可特化,适合复杂策略封装。

和 std::function 的区别:开销与灵活性取舍

std::function 是类型擦除容器,能装任何可调用物(函数指针、lambda、functor),但带来间接调用开销(虚函数或函数指针跳转)和内存分配可能(小对象优化虽存在,但不保证)。functor 是具体类型,零成本抽象:

简单说:写算法库、STL 风格组件、性能敏感路径,优先用 functor;做配置驱动、插件系统、回调注册,再考虑 std::function

容易踩的坑:const 正确性、移动语义和模板参数推导

常见错误集中在三个地方:

最隐蔽的问题是 functor 对象被算法多次复制却没意识到——比如在 std::transform 中每个元素都 new 一个内部缓存,结果创建了 N 份冗余状态。真正需要共享状态时,应通过指针或引用传递,而非依赖 functor 本身。