C++中的函数包装器(Function Wrapper)是用来封装和管理函数或可调用对象(如函数指针、函数对象、Lambda 表达式等)的工具。它们使得函数的使用更为灵活和通用,常被用于异步编程、事件处理、回调等场景。
C++11引入的 std::function 是最常用的函数包装器。它可以存储任何可调用对象并提供统一的调用接口。以下是关于函数包装器的详细讲解,包括它的基本用法、特点、限制、以及与其他相关机制的对比。
std::function 是 C++ 标准库中的一个模板类,可以存储一个可调用对象,如普通函数、函数指针、Lambda 表达式、或实现了 operator() 的对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#include <iostream> #include <functional>
void myFunction(int x) { std::cout << "Function called with: " << x << std::endl; }
int main() { std::function<void(int)> func = myFunction; // 包装普通函数
func(10); // 输出: Function called with: 10
// 也可以包装 Lambda 表达式 func = [](int y) { std::cout << "Lambda called with: " << y << std::endl; };
func(20); // 输出: Lambda called with: 20
return 0; } |
std::function 可以存储任何可以调用的对象,包括函数、Lambda 表达式和函数对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
#include <iostream> #include <functional>
int add(int a, int b) { return a + b; }
struct Multiply { int operator()(int a, int b) const { return a * b; } };
int main() { std::function<int(int, int)> func;
// 包装普通函数 func = add; std::cout << "Add: " << func(3, 4) << std::endl; // 输出: Add: 7
// 包装函数对象 func = Multiply(); std::cout << "Multiply: " << func(3, 4) << std::endl; // 输出: Multiply: 12
// 包装 Lambda 表达式 func = [](int a, int b) { return a - b; }; std::cout << "Subtract: " << func(10, 4) << std::endl; // 输出: Subtract: 6
return 0; } |
C++14引入了泛型Lambda,进一步增强了 std::function 的灵活性:
1 2 3 4 5 6 7 8 9 10 11 12 |
#include <iostream> #include <functional>
int main() { // 使用 Lambda 表达式的类型推导 auto lambda = [](int x) { return x * 2; }; std::function<int(int)> func = lambda;
std::cout << "Lambda result: " << func(5) << std::endl; // 输出: Lambda result: 10
return 0; } |
std::function 提供强类型安全,确保传递的可调用对象与指定的函数签名相符。
std::function 是一个类型擦除(Type Erasure)机制的实现,它会根据保存的可调用对象的类型动态分配内存。尽管这使得类型更灵活,但也增加了一些运行时开销。
由于类型擦除的特性,std::function 的性能通常低于直接使用函数指针或 Lambda 表达式,特别是在高频调用的场景下。如果对性能有较高要求,建议直接使用函数指针或模板。
std::bind 是一个C++11引入的函数适配器,允许将某些参数绑定到函数对象或 Lambda 表达式。与 std::function 结合使用可以使代码更灵活。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#include <iostream> #include <functional>
void print(int x, int y) { std::cout << "x: " << x << ", y: " << y << std::endl; }
int main() { // 使用 std::bind 绑定部分参数 auto boundFunc = std::bind(print, 10, std::placeholders::_1);
// `boundFunc` 现在只需要一个参数 boundFunc(20); // 输出: x: 10, y: 20
return 0; } |
在使用异步处理时,std::function 可以存储要在新线程中执行的函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
#include <iostream> #include <functional> #include <thread>
void asyncTask(int id) { std::cout << "Task " << id << " is running." << std::endl; }
int main() { // 声明 std::function std::function<void(int)> task = asyncTask;
// 创建新线程 std::thread t(task, 1); t.join(); // 等待线程结束
return 0; } |