1. 为什么需要函数包装器?
在C++开发中,我们经常会遇到需要处理多种可调用对象的情况。比如下面这个典型场景:
cpp复制template<class F, class T>
T useF(F f, T x)
{
static int count = 0;
cout << "count:" << ++count << endl;
cout << "count:" << &count << endl;
return f(x);
}
// 普通函数
double f(double i) { return i / 2; }
// 仿函数
struct Functor {
double operator()(double d) { return d / 3; }
};
int main()
{
cout << useF(f, 11.11) << endl; // 普通函数
cout << useF(Functor(), 11.11) << endl; // 仿函数
cout << useF([](double d){ return d/4; }, 11.11) << endl; // lambda
return 0;
}
这段代码看似简单,但实际上隐藏着一个性能问题:useF模板会为每种不同类型的可调用对象都实例化一份代码。也就是说,普通函数、仿函数和lambda表达式会导致useF被实例化三次,生成三份几乎相同的机器码。
提示:可以通过观察静态变量count的地址来验证实例化次数。如果地址不同,说明是不同实例。
这种重复实例化不仅增加了代码体积,还可能影响缓存命中率。那么,有没有办法让不同类型的可调用对象都能以统一的形式传递给模板,从而避免多次实例化呢?这就是function包装器要解决的问题。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. function包装器详解
2.1 function的基本用法
function是C++11引入的一个类模板,定义在
cpp复制#include <functional>
std::function<返回值类型(参数类型列表)> 包装器名称 = 可调用对象;
让我们看一个完整的示例:
cpp复制#include <iostream>
#include <functional>
using namespace std;
int add(int a, int b) { return a + b; }
struct Multiply {
int operator()(int a, int b) { return a * b; }
};
int main() {
// 包装普通函数
function<int(int, int)> f1 = add;
cout
