一、std::function
是什么?
std::function
是 C++11 引入的通用函数封装器,可以容纳任何“可调用对象”:
- 普通函数
- Lambda 表达式(含捕获)
- 函数指针
- 成员函数绑定(如
std::bind
) - 可调用类或仿函数(
operator()
)
它是 <functional>
中定义的模板类:
template< class R, class... Args >
class function<R(Args...)>;
意味着 std::function<void(int)>
表示可接收一个 int
参数、无返回值的任何可调用对象。
二、应用场景总结
场景 | 描述 |
---|---|
回调机制 | 可存储传入的回调函数(例如事件触发、完成通知) |
异步任务调度 | 用作任务队列中的任务封装 |
策略模式 | 在运行时动态替换策略行为(如算法接口) |
通用函数接口 | 支持用户传入任意处理逻辑,提高系统模块化 |
三、与函数指针的比较
特性 | 函数指针 | std::function |
---|---|---|
只支持普通函数 | ✅ | ✅ |
支持 lambda | ❌ | ✅ |
支持捕获 lambda | ❌ | ✅ |
支持成员函数(对象) | 部分(需要绑定) | ✅(支持 std::bind 或 lambda) |
类型安全、泛型 | ❌ | ✅ |
内存开销 | 较小 | 较大,但可忽略(有类型擦除) |
四、代码示例
1. 基础用法:封装函数、lambda、函数指针
#include <iostream>
#include <functional>
void sayHello() {
std::cout << "Hello\n";
}
int add(int a, int b) {
return a + b;
}
int main() {
std::function<void()> f1 = sayHello;
f1(); // 输出:Hello
std::function<int(int, int)> f2 = add;
std::cout << f2(3, 4) << "\n"; // 输出:7
std::function<int(int, int)> f3 = [](int x, int y) {
return x * y;
};
std::cout << f3(2, 5) << "\n"; // 输出:10
}
2. 成员函数与绑定
#include <iostream>
#include <functional>
class Worker {
public:
void process(int x) {
std::cout << "Processing: " << x << "\n";
}
};
int main() {
Worker w;
// 绑定成员函数
std::function<void(int)> cb = std::bind(&Worker::process, &w, std::placeholders::_1);
cb(42); // 输出:Processing: 42
}
3. 捕获 lambda 作为回调
#include <iostream>
#include <functional>
void doSomething(std::function<void(int)> callback) {
for (int i = 0; i < 3; ++i) {
callback(i);
}
}
int main() {
int count = 0;
doSomething([&count](int x) {
count += x;
std::cout << "Got: " << x << ", total: " << count << "\n";
});
}
4. 与任务调度系统结合使用(轻量)
#include <iostream>
#include <vector>
#include <functional>
class TaskQueue {
public:
void addTask(const std::function<void()>& task) {
tasks_.push_back(task);
}
void run() {
for (auto& task : tasks_) {
task();
}
}
private:
std::vector<std::function<void()>> tasks_;
};
int main() {
TaskQueue q;
q.addTask([]() { std::cout << "Task A\n"; });
q.addTask([]() { std::cout << "Task B\n"; });
q.run(); // 输出 Task A 和 Task B
}
5. 回调注册系统(模拟事件中心)
#include <iostream>
#include <functional>
#include <vector>
class EventSystem {
public:
using Callback = std::function<void(int)>;
void registerCallback(const Callback& cb) {
callbacks_.push_back(cb);
}
void trigger(int val) {
for (auto& cb : callbacks_) {
cb(val);
}
}
private:
std::vector<Callback> callbacks_;
};
int main() {
EventSystem es;
es.registerCallback([](int x) { std::cout << "Callback A: " << x << "\n"; });
es.registerCallback([](int x) { std::cout << "Callback B: " << x * 2 << "\n"; });
es.trigger(5);
}
五、典型场景应用实战示例
下面是针对三种典型应用场景 —— 异步线程池、事件广播系统、插件系统接口 的 std::function
应用讲解与完整 C++ 示例代码。这三种结构中,std::function
是核心桥梁,用于高效、安全地封装任务、回调与动态行为。
1. 异步线程池任务封装
使用 std::function<void()>
封装任意任务并在线程中异步执行。
示例:轻量级线程池结构
#include <iostream>
#include <thread>
#include <queue>
#include <functional>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <atomic>
class ThreadPool {
public:
using Task = std::function<void()>;
ThreadPool(size_t threadCount = std::thread::hardware_concurrency()) {
running = true;
for (size_t i = 0; i < threadCount; ++i) {
workers.emplace_back([this]() {
while (running) {
Task task;
{
std::unique_lock<std::mutex> lock(mutex);
cond.wait(lock, [this]() {
return !taskQueue.empty() || !running;
});
if (!running && taskQueue.empty()) return;
task = std::move(taskQueue.front());
taskQueue.pop();
}
task();
}
});
}
}
~ThreadPool() {
running = false;
cond.notify_all();
for (auto& t : workers) {
if (t.joinable()) t.join();
}
}
void enqueue(Task task) {
{
std::lock_guard<std::mutex> lock(mutex);
taskQueue.push(std::move(task));
}
cond.notify_one();
}
private:
std::vector<std::thread> workers;
std::queue<Task> taskQueue;
std::mutex mutex;
std::condition_variable cond;
std::atomic<bool> running;
};
// 使用示例
int main() {
ThreadPool pool(4);
for (int i = 0; i < 5; ++i) {
pool.enqueue([i]() {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::cout << "Task " << i << " done\n";
});
}
}
2. 事件广播系统(Observer 模式)
std::function
用作回调函数注册,支持多个监听器。
示例:事件中心
#include <iostream>
#include <vector>
#include <functional>
class EventDispatcher {
public:
using Listener = std::function<void(int)>;
void addListener(const Listener& listener) {
listeners.push_back(listener);
}
void broadcast(int eventCode) {
for (auto& listener : listeners) {
listener(eventCode);
}
}
private:
std::vector<Listener> listeners;
};
// 使用示例
int main() {
EventDispatcher dispatcher;
dispatcher.addListener([](int code) {
std::cout << "Listener A received: " << code << "\n";
});
dispatcher.addListener([](int code) {
std::cout << "Listener B processed: " << code * 2 << "\n";
});
dispatcher.broadcast(100);
}
3. 插件系统接口封装
利用 std::function
封装动态传入的“行为实现”(比如一个插件模块提供的处理函数)。
示例:插件行为接口
#include <iostream>
#include <functional>
#include <memory>
class PluginInterface {
public:
using Callback = std::function<void(const std::string&)>;
void registerCallback(Callback cb) {
onMessage = cb;
}
void emitMessage(const std::string& msg) {
if (onMessage) onMessage(msg);
}
private:
Callback onMessage;
};
// 模拟插件
class MyPlugin {
public:
void attachTo(PluginInterface& iface) {
iface.registerCallback([this](const std::string& msg) {
std::cout << "[MyPlugin] received: " << msg << "\n";
});
}
};
// 使用示例
int main() {
PluginInterface iface;
MyPlugin plugin;
plugin.attachTo(iface);
iface.emitMessage("Hello from core system!");
}
总结
应用 | 用法 | std::function 类型 |
---|---|---|
线程池 | 封装任意任务 | std::function<void()> |
事件系统 | 注册/触发事件响应回调 | std::function<void(Event)> |
插件接口 | 动态注册功能实现 | std::function<void(const std::string&)> 或更复杂结构 |
六、最佳实践
- 若性能敏感且固定调用对象,用 函数指针或模板;
- 若需要灵活性、支持绑定 lambda/状态对象,优先使用
std::function
; - 尽量用
const std::function<>&
引用传参,避免拷贝; - 如果回调频繁被调用(如每帧),也可以结合
std::move
。