`std::function` 是 C++11 引入的通用函数包装器(定义于 `
## 基本用法:定义与调用
`std::function` 的模板参数为**函数签名**(返回类型 + 参数列表),格式为:
“` text
std::function<返回类型(参数类型1, 参数类型2, ...)>
“`
### 示例:包装不同类型的可调用对象
“`cpp
#include
#include
// 1. 普通函数
int add(int a, int b)
{
return a + b;
}
// 2. 仿函数(重载 operator() 的结构体)
struct Multiply
{
int operator()(int a, int b) { return a * b; }
};
int main()
{
// 包装普通函数
std::function
// 输出:5
std::cout << func1(2, 3) << std::endl;
// 包装仿函数
std::function
// 输出:6
std::cout << func2(2, 3) << std::endl;
// 包装 lambda 表达式
std::function
// 输出:3
std::cout << func3(5, 2) << std::endl;
// 包装函数指针
int (*sub_ptr)(int, int) = [](int a, int b) { return a - b; };
// lambda 转换为函数指针(无捕获时)
std::function
// 输出:2
std::cout << func4(5, 3) << std::endl;
return 0;
}
```
## 核心特性:存储与传递可调用对象
`std::function` 的核心价值是**统一不同可调用对象的类型**,便于存储和传递(如作为函数参数、返回值、容器元素)。
### 1. 作为函数参数(回调函数场景)
```cpp
// 接收 std::function 作为参数,实现通用回调
void process(int a, int b, std::function
{
std::cout << "结果: " << op(a, b) << std::endl;
}
int main()
{
// 普通函数作为回调
process(10, 5, add);
// 仿函数作为回调
process(10, 5, Multiply{});
// lambda 作为回调
process(10, 5, [](int a, int b) { return a / b; });
return 0;
}
```
### 2. 作为函数返回值
```cpp
// 根据条件返回不同的运算函数
std::function
{
switch (op)
{
case ‘+’:
return add;
case ‘*’:
return Multiply{};
case ‘-‘:
return [](int a, int b) { return a – b; };
default:
return [](int, int) { return 0; };
}
}
int main()
{
auto op = GetOperator(‘*’);
// 输出:12
std::cout << op(3, 4) << std::endl;
return 0;
}
```
### 3. 作为容器元素
```cpp
#include
int main()
{
std::vector
// 乘以 2
funcs.push_back([](int x) { return x * 2; });
// 加 10
funcs.push_back([](int x) { return x + 10; });
// 平方
funcs.push_back([](int x) { return x * x; });
int x = 3;
for (auto& f : funcs)
{
std::cout << f(x) << " "; // 输出:6 13 9
}
return 0;
}
```
### 3. 结合 `std::bind` 绑定参数
`std::function`配合`std::bind`,固定部分参数,返回新的可调用对象。
```cpp
#include
// 原函数:3个参数
int sum(int a, int b, int c)
{
return a + b + c;
}
int main()
{
// 绑定前两个参数为 10 和 20,仅保留最后一个参数
// std::placeholders::_n 表示“第n个未绑定的参数”,调用时需传入。
auto bindFunc = std::bind(sum, 10, 20, std::placeholders::_1);
// 用 std::function 包装绑定后的函数(此时只需 1 个参数)
std::function
// 10 + 20 + 30 = 60
std::cout << func(30) << std::endl;
return 0;
}
```
### 4. 绑定成员函数
`std::function` 可通过绑定具体对象或指针包装类的成员函数。
```cpp
#include
#include
class Math
{
public:
int pow(int a, int b)
{
// 成员函数
int res = 1;
for (int i = 0; i < b; ++i)
{
res *= a;
}
return res;
}
};
int main()
{
Math m;
// 包装成员函数:需传入对象指针 + 成员函数地址
// 成员函数的第一个隐含参数是 this指针,因此绑定需显式传入对象(或指针)。
std::function
std::placeholders::_1,
std::placeholders::_2);
// 2^3 = 8
std::cout << func(2, 3) << std::endl;
return 0;
}
```
## 总结
### 1. 主要用法
`std::function`是C++中统一可调用对象的“万能容器”,主要用法包括:
- 包装函数、lambda、仿函数等可调用对象;
- 作为参数传递(回调函数)、作为返回值(函数工厂)、作为容器元素;
- 结合 `std::bind` 处理参数绑定和成员函数;
- 需注意空状态检查和对象生命周期。
### 2. 注意事项
1. **性能开销**:`std::function` 内部通过类型擦除实现,调用时会有轻微的性能损耗(比直接调用函数指针略慢),但通常可忽略。
2. **生命周期管理**:若包装的是捕获了引用的 lambda 或绑定了局部对象的 `std::bind` 表达式,需确保引用的对象生命周期长于 `std::function`,否则会导致未定义行为。
3. **不可拷贝的可调用对象**:`std::function` 要求存储的可调用对象是**可拷贝的**,若对象不可拷贝(如 `std::unique_ptr` 捕获到 lambda 中),则无法存储(C++17 起可部分支持移动语义)。
4. **与 lambda 的配合**:无捕获的 lambda 可隐式转换为函数指针,而有捕获的 lambda 只能通过 `std::function` 包装。

