在 C++11 及以后的标准中,std::function 是一个极具价值的函数包装器模板 ,隶属于<functional>头文件。它能统一封装所有可调用对象 (普通函数、函数指针、仿函数、Lambda 表达式、类成员函数等),形成一个通用、可赋值、可存储的函数对象,让 C++ 的回调、策略模式、函数管理变得更加简洁优雅。
本文从核心概念、用法、场景、示例全方位讲解std::function,帮你快速掌握这个现代 C++ 必备工具。
一、什么是 std::function?
1. 核心定义
std::function 是一个通用、类型安全的可调用对象包装器:
它是一个模板类,可以 "包裹" 任何符合签名的可调用对象;
对外提供统一的调用接口,无视底层可调用对象的类型;
可以像普通变量一样赋值、拷贝、存储、作为参数传递。
简单理解:std::function = 万能函数容器,只要返回值和参数一致,任何可调用对象都能装进去。
2. 语法格式
cpp
#include <functional> // 必须包含
// 格式:
std::function<返回值类型(参数类型1, 参数类型2...)> 变量名;
示例:定义一个能包装 "接收两个 int、返回 int" 的函数包装器
cpp
function<int(int, int)> func;
二、std::function 能包装什么?
std::function 可以统一包装4 大类可调用对象:
1. 普通函数
cpp
int add(int a, int b) { return a + b; }
function<int(int, int)> f = add;
cout << f(10, 20) << endl; // 30
- Lambda 表达式(最常用)
cpp
function<int(int, int)> f = [](int a, int b) { return a * b; };
cout << f(10, 20) << endl; // 200
- 仿函数(函数对象)
cpp
class Sub {
public:
int operator()(int a, int b) { return a - b; }
};
function<int(int, int)> f = Sub();
cout << f(20, 10) << endl; // 10
- 类成员函数(需绑定对象)
cpp
class Test {
public:
int mul(int a, int b) { return a * b; }
};
Test obj;
function<int(Test&, int, int)> f = &Test::mul;
cout << f(obj, 10, 20) << endl; // 200
三、核心优势:为什么要用 function?
1. 统一所有可调用对象类型
没有function时,不同可调用对象类型不同,无法存入同一个容器;有了function,类型不同、功能相同的函数可以统一管理。
示例:同一容器存储不同类型函数
cpp
#include <iostream>
#include <functional>
#include <vector>
using namespace std;
int main() {
// 统一函数签名:int(int,int)
vector<function<int(int, int)>> vec;
// 放入 普通函数、Lambda、仿函数
vec.push_back([](int a,int b){return a+b;});
vec.push_back([](int a,int b){return a*b;});
cout << vec[0](10,20) << endl; // 30
cout << vec[1](10,20) << endl; // 200
return 0;
}
2. 轻松实现回调函数
以往用函数指针实现回调,语法复杂、不支持 Lambda / 仿函数;
function 让回调简单、直观、灵活。
示例:回调函数
cpp
// 接收一个function作为回调
void doWork(function<void()> callback) {
cout << "执行任务..." << endl;
callback(); // 调用回调
}
int main() {
doWork([](){ cout << "回调执行!" << endl; });
return 0;
}
3. 可重新赋值,灵活切换函数
普通函数指针赋值受限,function 可以随时更换包装的函数:
cpp
function<int(int,int)> f;
f = [](int a,int b){return a+b;};
cout << f(10,20); // 30
f = [](int a,int b){return a*b;};
cout << f(10,20); // 200
四、完整使用示例(全能演示)
cpp
#include <iostream>
#include <functional>
using namespace std;
// 1. 普通函数
int add(int a, int b) { return a + b; }
// 2. 仿函数
class Mul {
public:
int operator()(int a, int b) { return a * b; }
};
int main() {
// 定义function包装器:int(int,int)
function<int(int, int)> func;
// 包装普通函数
func = add;
cout << "add: " << func(10, 20) << endl;
// 包装Lambda
func = [](int a, int b) { return a - b; };
cout << "sub: " << func(20, 10) << endl;
// 包装仿函数
func = Mul();
cout << "mul: " << func(10, 20) << endl;
return 0;
}
输出:
cpp
add: 30
sub: 10
mul: 200
五、常用场景
std::function 在实际开发中高频使用:
- 回调函数:按钮点击、异步完成、事件触发;
- 策略模式:动态切换算法逻辑(排序、过滤、处理规则);
- 函数容器 :把函数存入
vector/map统一管理; - 延迟执行:保存函数,后续再调用;
- 替代复杂函数指针:语法更简洁、可读性更高。
六、注意事项
- 必须包含头文件 :
<functional>; - 包装时签名必须一致:返回值 + 参数类型必须严格匹配;
- 空 function 调用会抛异常 :使用前可判断
if(func); - 包装成员函数时:必须传入对象作为第一个参数;
- 性能极高:几乎无额外开销,可放心使用。
总结
std::function:C++11 函数包装器,统一封装所有可调用对象;- 包装类型:普通函数、Lambda、仿函数、类成员函数;
- 核心价值:统一类型、实现回调、灵活赋值、管理函数集合;
- 语法 :
function<返回值(参数)>; - 地位 :现代 C++ 回调、函数管理的标准方案。
std::function 让 C++ 的函数操作更加现代化、优雅化,是必须掌握的核心模板。