std::function是C++11引入的标准库组件,定义在functional头文件中,它可以存储、复制和调用任何可调用对象,是C++中实现函数包装和回调功能的核心工具之一。它的灵活性让开发者可以统一处理不同类型的函数逻辑,降低代码的耦合度。

std::function的基本定义与初始化
std::function本身是一个模板类,使用时需要指定它包装的可调用对象的返回类型和参数类型。基本定义格式为std::function<返回类型(参数类型列表)>。
包装普通函数
普通函数的类型匹配时,可以直接赋值给std::function对象:
#include <functional>
#include <iostream>
// 普通函数
int add(int a, int b) {
return a + b;
}
int main() {
// 定义包装两个int参数返回int的函数包装器
std::function<int(int, int)> func;
// 绑定普通函数
func = add;
// 调用包装器
std::cout << "add result: " << func(1, 2) << std::endl;
return 0;
}
包装lambda表达式
lambda表达式是std::function最常用的绑定对象之一,适配性非常强:
#include <functional>
#include <iostream>
int main() {
// 包装lambda表达式
std::function<int(int, int)> func = [](int a, int b) {
return a * b;
};
std::cout << "lambda result: " << func(3, 4) << std::endl;
return 0;
}
包装成员函数
绑定类的成员函数时,需要配合std::bind或者lambda表达式来传递对象实例:
#include <functional>
#include <iostream>
class Calculator {
public:
int sub(int a, int b) {
return a - b;
}
};
int main() {
Calculator calc;
// 方式1:使用lambda绑定成员函数
std::function<int(int, int)> func1 = [&calc](int a, int b) {
return calc.sub(a, b);
};
// 方式2:使用std::bind绑定
std::function<int(int, int)> func2 = std::bind(&Calculator::sub, &calc, std::placeholders::_1, std::placeholders::_2);
std::cout << "sub result1: " << func1(5, 2) << std::endl;
std::cout << "sub result2: " << func2(5, 2) << std::endl;
return 0;
}
std::function实现回调函数
回调函数的核心是把一个函数作为参数传递给另一个函数,在合适的时机被调用。std::function可以统一回调函数的类型,让回调的实现更灵活。
基础回调实现
下面的例子演示了事件触发时调用回调函数的场景:
#include <functional>
#include <iostream>
#include <vector>
// 定义回调函数类型:无参数无返回值
using Callback = std::function<void()>;
class EventSystem {
private:
std::vector<Callback> callbacks;
public:
// 注册回调函数
void register_callback(Callback cb) {
callbacks.push_back(cb);
}
// 触发所有回调
void trigger_event() {
for (auto& cb : callbacks) {
if (cb) { // 检查包装器是否有效
cb();
}
}
}
};
int main() {
EventSystem es;
// 注册第一个回调
es.register_callback([]() {
std::cout << "callback 1 triggered" << std::endl;
});
// 注册第二个回调
es.register_callback([]() {
std::cout << "callback 2 triggered" << std::endl;
});
// 触发事件
es.trigger_event();
return 0;
}
带参数的回调实现
回调也可以携带参数,只需要调整std::function的模板参数即可:
#include <functional>
#include <iostream>
#include <string>
// 带参数的回调类型:接收string和int参数
using DataCallback = std::function<void(const std::string&, int)>;
class DataProcessor {
private:
DataCallback callback;
public:
void set_callback(DataCallback cb) {
callback = cb;
}
void process_data(const std::string& name, int value) {
// 处理数据逻辑
int result = value * 2;
// 处理完成后调用回调
if (callback) {
callback(name, result);
}
}
};
int main() {
DataProcessor processor;
processor.set_callback([](const std::string& name, int result) {
std::cout << "process " << name << " result: " << result << std::endl;
});
processor.process_data("test_data", 10);
return 0;
}
std::function使用注意事项
- std::function包装的对象如果为空,直接调用会抛出
std::bad_function_call异常,调用前最好先判断有效性,或者用try-catch捕获异常。 - 包装成员函数时,需要注意绑定的对象生命周期,避免对象已经被释放后还调用回调,导致悬空引用问题。
- std::function的性能比直接调用函数稍差,因为它内部有虚函数调用开销,在对性能要求极高的场景需要谨慎使用。
- 可以用
std::function::target方法获取内部存储的原始可调用对象,但一般场景下不需要用到这个接口。
常见使用场景总结
std::function的典型使用场景包括:事件系统回调、线程池任务封装、策略模式实现、延迟执行逻辑封装等。它让C++的函数传递变得更统一,不需要再针对不同类型的可调用对象写多套逻辑,大幅提升了代码的复用性和可读性。
std::function回调函数函数包装器C++11修改时间:2026-06-26 07:48:27