一、std::function
1.1 std::function 介绍
std::function 是 C++11 引入的标准库组件(定义在 <functional> 头文件中),它是一种通用的函数包装器,可以存储、复制和调用任何可调用对象(callable object),包括普通函数、lambda 表达式、函数指针、仿函数(functor)、成员函数指针等。其核心作用是提供一种统一的接口来处理各种不同类型的可调用对象,简化函数作为参数传递、存储或延迟调用的场景。
1.2 std::function 的使用
std::function主要用于包装可调用对象,包括:
- 普通函数
- lambda 表达式
- 函数指针
- 仿函数(重载了
operator()的类对象) - 类的成员函数(需要配合
std::bind或 lambda 绑定this指针)
下面是一个使用std::function包装可调用对象的例子:
#include<iostream>
#include<functional>
using namespace std;
void printA(int a){
std::cout << a << std::endl;
}
class Foo{
public:
Foo(int num):num_(num){}
void print_add(int x){
std::cout <<"print_add: " << num_ + x << std::endl;
}
private:
int num_;
};
int main(){
//包装普通函数
std::function<void(int a)>func;
func = printA;
func(10);
//包装lambada
std::function<void()>func2 = [](){ std::cout << "lambada" << std::endl; };
func2();
//保存成员函数
std::function<void(Foo&,int)> f_add_display(&Foo::print_add);
Foo foo(2);
f_add_display(foo,10);
return 0;
}
运行结果如下:

二、std::bind
2.1 std::bind 介绍
std::bind 是 C++11 引入的标准库工具(定义在 <functional> 头文件中),用于绑定可调用对象(如函数、lambda、成员函数等)的参数,生成一个新的可调用对象。其核心功能是 “固定” 原函数的部分或全部参数,或调整参数的传递顺序,从而在后续调用时简化参数传递。
2.2 std::bind 的使用
-
使用
std::bind的时候,可以使用std::placeholders::_1、std::placeholders::_2等占位符包装可调用对象,返回的一个对象仍然是可调用对象,不过,此时的可调用对象参数数量已经改变了,只需要传入占位符的参数即可 -
使用占位符的名字和函数参数有严格对应关系,比如
std::placeholders::_1就代表需要传入的第一个参数,std::placeholders::_2则为第二个参数,与顺序无关 -
通过
std::bind提前传入的参数使用的是值传入,也就是说如果函数形参是引用&的话,将不会改变传入的参数,此时应该使用std::ref或常引用std::cref传入参数
下面是一个使用std::bind绑定参数的例子
#include<iostream>
#include<functional>
using namespace std;
class A
{
public:
void fun_3(int k,int m)
{
cout<<"print: k="<< k << ",m="<< m << endl;
}
};
void fun_1(int x,int y,int z){
cout<<"print: x=" << x << ",y=" << y <<",z=" << z << endl;
}
void fun_2(int& x,int& y){
x++,y++;
cout<<"print: x=" << x << ",y=" << y << endl;
}
int main(){
//示绑定函数 fun 的第一,二,三个参数值为: 1 2 3
auto f1 = std::bind(fun_1,1,2,3); //返回类型为std::function<void(int,int,int)>
f1();
//表示绑定函数 fun 的第三个参数为 3,而fun 的第一,二个参数分别由调用 f2 的第一,二个参数指定
auto f2 = std::bind(fun_1,placeholders::_1,placeholders::_2,3);
f2(1,2);
//表示绑定函数 fun 的第三个参数为 3,而fun 的第一,二个参数分别由调用 f3 的第二,一个参数指定
auto f3 = std::bind(fun_1,placeholders::_2,placeholders::_1,3); //注意和f2区分
f3(1,2);
int m = 2;
int n = 3;
//表示绑定fun_2的第一个参数为n,fun_2的第二个参数由调用f4的第一个参数(_1)指定。
auto f4 = std::bind(fun_2, placeholders::_1, n);
f4(m);
// 说明:bind对于预先绑定的函数参数是通过值传递的,如n
//说明:bind对于不事先绑定的参数,通过std::placeholders传递的参数是通过引用传递的,如m
std::cout << "m=" << m << ", =" << n << std::endl;
A a;
auto f5 = std::bind(&A::fun_3,a,placeholders::_1,placeholders::_2);
f5(10,20);//调用a.fun_3(10,20),print: k=10,m=20
return 0;
}
运行结果如下:

2.3 与lambda表达式对比
lambda表达式也可以适配参数,主要通过捕获外部变量和自定义参数列表来实现,比如下面的例子:
将一个需要 3 个参数的函数,固定其中 2 个参数,只保留 1 个参数动态传入:
#include <iostream>
// 原函数:a + b * c
int calculate(int a, int b, int c) {
return a + b * c;
}
int main() {
// 固定 b=2, c=3,只动态传入 a(通过 lambda 捕获固定参数)
int fixed_b = 2;
int fixed_c = 3;
auto lambda_func = [fixed_b, fixed_c](int a) {
return calculate(a, fixed_b, fixed_c); // 使用捕获的固定参数
};
// 调用时只需传入 a
std::cout << lambda_func(1) << std::endl; // 等价于 calculate(1, 2, 3) → 7
std::cout << lambda_func(5) << std::endl; // 等价于 calculate(5, 2, 3) → 11
return 0;
}
lambda 与 std::bind 的适配能力对比
| 适配场景 | lambda 实现方式 | std::bind 实现方式 |
|---|---|---|
| 固定部分参数 | 捕获外部变量 | 使用具体值 + 占位符(_1、_2) |
| 调整参数顺序 | 自定义参数列表,手动重排 | 占位符调整顺序(_2 作为第一个参数等) |
| 传递引用参数 | 引用捕获([&x]) | std::ref(x) 或 std::cref(x) |
| 绑定成员函数 | 捕获对象 / 指针,直接调用成员函数 | &Class::func, 对象指针, 占位符 |
| 复杂参数适配(多参数重排) | 需手动处理,但逻辑可见 | 占位符组合(如 _3, _1, _2) |

2452

被折叠的 条评论
为什么被折叠?



