C++标准库中的std::function是定义于functional头文件的函数包装器,它可以存储、复制和调用任何可调用目标,包括普通函数、lambda表达式、成员函数指针、函数对象等,为函数作为一等公民参与逻辑处理提供了便利。

std::function的基本定义与初始化
std::function是一个模板类,定义时需要指定它包装的可调用目标的返回类型和参数类型,格式为std::function<返回类型(参数类型列表)>。我们可以通过多种方式为std::function对象赋值初始化。
封装普通函数
普通函数是std::function最常见的封装对象之一,只要函数的签名和std::function的模板参数匹配即可直接赋值。
#include <iostream>
#include <functional>
// 普通函数,接受两个int参数,返回int
int add(int a, int b) {
return a + b;
}
int main() {
// 定义std::function对象,匹配普通函数的签名
std::function<int(int, int)> func;
// 将普通函数赋值给std::function对象
func = add;
// 调用std::function对象,等价于调用add函数
int result = func(3, 5);
std::cout << "计算结果:" << result << std::endl;
return 0;
}
封装lambda表达式
lambda表达式是C++11引入的匿名函数,和std::function配合使用时非常灵活,尤其是在需要传递简短回调逻辑的场景中。
#include <iostream>
#include <functional>
int main() {
// 定义std::function对象,匹配lambda的签名
std::function<int(int, int)> multiply;
// 将lambda表达式赋值给std::function对象
multiply = [](int a, int b) {
return a * b;
};
// 调用lambda封装后的函数
int res = multiply(4, 6);
std::cout << "乘法结果:" << res << std::endl;
return 0;
}
封装函数对象
函数对象是重载了operator()的类实例,同样可以被std::function封装,适合需要携带状态的场景。
#include <iostream>
#include <functional>
// 定义函数对象类
class Counter {
public:
Counter(int init) : count(init) {}
// 重载operator()
int operator()() {
return ++count;
}
private:
int count;
};
int main() {
Counter counter(10);
// 封装函数对象,签名是无参数返回int
std::function<int()> func = counter;
std::cout << "计数1:" << func() << std::endl;
std::cout << "计数2:" << func() << std::endl;
return 0;
}
封装类成员函数
类的非静态成员函数需要依赖对象实例才能调用,因此封装时需要结合对象指针或者std::bind来绑定对象。
#include <iostream>
#include <functional>
class Calculator {
public:
int subtract(int a, int b) {
return a - b;
}
};
int main() {
Calculator calc;
// 使用std::bind绑定成员函数和对象实例
std::function<int(int, int)> subFunc = std::bind(&Calculator::subtract, &calc, std::placeholders::_1, std::placeholders::_2);
int subRes = subFunc(10, 3);
std::cout << "减法结果:" << subRes << std::endl;
return 0;
}
std::function的实践应用场景
std::function在实际开发中有很多实用场景,最常见的就是作为回调函数使用,降低模块之间的耦合度。
回调机制实现
比如在事件处理模块中,我们可以定义std::function类型的回调成员变量,外部模块可以传入不同的处理逻辑。
#include <iostream>
#include <functional>
#include <vector>
// 事件处理器类
class EventHandler {
public:
// 注册事件回调,回调是无参数无返回值的函数
void registerCallback(std::function<void()> cb) {
callbacks.push_back(cb);
}
// 触发所有注册的回调
void triggerEvent() {
for (auto& cb : callbacks) {
cb();
}
}
private:
std::vector<std::function<void()>> callbacks;
};
int main() {
EventHandler handler;
// 注册第一个回调
handler.registerCallback([]() {
std::cout << "事件回调1执行" << std::endl;
});
// 注册第二个回调
handler.registerCallback([]() {
std::cout << "事件回调2执行" << std::endl;
});
// 触发事件
handler.triggerEvent();
return 0;
}
函数容器存储
我们还可以用容器存储多个std::function对象,实现类似命令模式的逻辑,比如批量执行一组函数。
#include <iostream>
#include <functional>
#include <vector>
int main() {
std::vector<std::function<void()>> taskList;
// 向容器中添加不同的函数逻辑
taskList.push_back([]() {
std::cout << "执行任务1" << std::endl;
});
taskList.push_back([]() {
std::cout << "执行任务2" << std::endl;
});
// 批量执行所有任务
for (auto& task : taskList) {
task();
}
return 0;
}
使用注意事项
使用std::function时需要注意几个问题,首先是它封装的可调用目标签名必须和模板参数完全匹配,否则会导致编译错误。其次,空的std::function对象调用会抛出std::bad_function_call异常,在调用前最好先判断是否为空:
#include <iostream>
#include <functional>
int main() {
std::function<int(int)> emptyFunc;
if (emptyFunc) {
emptyFunc(10);
} else {
std::cout << "std::function对象为空,无法调用" << std::endl;
}
return 0;
}
另外,std::function会带来一定的性能开销,因为它内部需要维护类型擦除的逻辑,在对性能要求极高的场景需要谨慎使用。
std::functionC++函数封装lambda表达式修改时间:2026-06-15 06:48:44