std::function: 一个通用的函数封装器,它允许你存储和调用任何可以被调用的东西,例如函数、函数指针、函数对象、Lambda 表达式等。
std::bind: 用于创建函数对象。一个可调用对象的绑定版本,可以提前绑定某些参数,稍后调用时只需提供剩余的参数。
在某些情况下,你可以将它们结合使用,例如,如果你想创建一个可调用对象,该对象包含绑定的参数,然后将其存储在 std::function 中。这在某些情况下可以提高代码的可读性和灵活性。
示例:
#include <iostream>
#include <functional>int add(int a, int b) {return a + b;
}int main() {// 创建一个绑定了参数的可调用对象,绑定参数为2,// 占位符_1表示稍后调用时传入的第1个参数放在_1这个位置std::function<int(int)> func = std::bind(add, 2, std::placeholders::_1);// 调用 std::functionint result = func(3); // 这里相当于调用 add(2, 3)std::cout << "Result: " << result << std::endl;return 0;
}
将std::function与std::bind一起使用可以提供一些好处,尤其在以下情况下:
-
延迟参数绑定:你可以使用std::bind在创建std::function对象时部分绑定参数,然后稍后再提供其余的参数。这使得你可以在调用可调用对象时动态地确定一些参数值。
-
增强可读性:std::bind允许你清晰地指定参数的绑定方式,这可以提高代码的可读性,特别是当你处理复杂的函数签名时。
-
灵活性:结合使用std::function和std::bind可以让你更容易地操作和传递可调用对象。这对于实现通用接口或处理回调函数时特别有用。
-
减少代码冗余:如果你需要多次调用具有相同部分绑定的可调用对象,结合使用std::function和std::bind可以减少重复的绑定代码。
在不需要提前绑定参数的情况下,可以不使用std::bind()。在C++11引入Lambda表达式后,使用更加灵活和方便。以下是一个示例,演示如何使用 std::function 存储一个普通函数或Lambda表达式
Copy code
#include <iostream>
#include <functional>// 普通函数
int add(int a, int b) {return a + b;
}int main() {// 使用 std::function 存储普通函数std::function<int(int, int)> func1 = add;// 使用 Lambda 表达式std::function<int(int, int)> func2 = [](int a, int b) {return a + b;};int result1 = func1(2, 3); // 调用 add 函数int result2 = func2(4, 5); // 调用 Lambda 表达式std::cout << "Result 1: " << result1 << std::endl;std::cout << "Result 2: " << result2 << std::endl;return 0;
}
考虑这种情况:可调用对象是类的普通成员函数
- 成员函数是跟具体的对象绑定的,它可以操作该对象中的其他成员变量或者调用其他成员函数。成员函数可以做到分辨哪个对象在调用我是因为有隐藏
this
指针指向当前调用该函数的对象。 - 比如
obj.funcAdd(1,2)
,效果实际上是Obj::funcAdd(&obj, 1, 2);
。 - 因此如果可调用对象是普通成员函数,我们要绑定一个参数,即指向调用对象的指针。
因此,比较推荐std::function与std::bind()配合使用,或者用lambda表达式
-
当在一个成员函数中创建函数指针指向另一个普通成员函数时,绑定参数为
this
#include <iostream> #include <functional>class MyClass { public:void func1(int value) {std::cout << "func1: " << value << std::endl;}void func2(int value) {std::cout << "func2: " << value << std::endl;}void doSome() {// 使用 std::bind 创建 std::function 对象,将其绑定到 func2std::function<void(MyClass*, int)> functionPtr = std::bind(&MyClass::func2, this, std::placeholders::_2);// 调用函数指针,传入对象实例指针和参数functionPtr(42);} };int main() {MyClass obj;obj.doSome();return 0; }
当然也可以手动传入this
比如:std::bind(&MyClass::func2, std::placeholders::_1, std::placeholders::_2);
调用:functionPtr(this, 42);
-
利用lambda表达式作为可调用对象
#include <iostream> #include <functional>class MyClass { public:void func1(int value) {std::cout << "func1: " << value << std::endl;}void func2(int value) {std::cout << "func2: " << value << std::endl;}void doSome() {// 使用 Lambda 表达式捕获 this 指针std::function<void(int)> functionPtr = [this](int value) {MemberFunction2(value);};// 调用函数指针,不需要传递 this 指针functionPtr(42);} };int main() {MyClass obj;obj.doSome();return 0; }
-
还有一种简单的情况:如果是在想存储某个对象的某个成员函数的指针,则需要传入该对象的地址
#include <iostream> #include <functional>class MyClass { public:void func(int value) {std::cout << "func: " << value << std::endl;} };int main() {MyClass obj;// 创建 std::function 对象,提前绑定&obj,如果不绑定则需要手动传入std::function<void(int)> funcPtr = std::bind(&MyClass::func, &obj, std::placeholders::_1);funcPtr(42);return 0; }