std::function
和 std::bind
是 C++11 标准库中引入的两个重要组件,用于实现函数对象的封装和绑定。它们为 C++ 中的函数式编程提供了更加灵活和方便的方式。可以用于实现回调函数的思想。
std::function
std::function
是一个模板类,用于封装任意可调用对象(函数指针、函数对象、成员函数指针、lambda 表达式等),并提供一种统一的接口来调用这些对象。它可以看作是一个类型安全的函数指针的容器。
特点:
std::function
是可调用对象的包装器,它可以存储、复制和调用任何可调用对象。
std::function
的类型由其模板参数确定,因此它可以表示各种不同的函数类型。
std::function
对象可以在运行时被赋予不同的可调用对象,并且可以被多次复制、传递和调用。
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #include <iostream> #include <functional>
void say_hello() { std::cout << "Hello, world!" << std::endl; }
int add(int a, int b) { return a + b; }
int main() { std::function<void()> func1 = say_hello; func1();
std::function<int(int, int)> func2 = add; std::cout << "Sum: " << func2(3, 4) << std::endl;
return 0; }
|
std::bind
std::bind
是一个函数模板,用于创建一个新的可调用对象。该对象会将参数绑定到函数或函数对象上。它允许延迟绑定参数,以后再调用时传递剩余的参数。
语法:
1 2 3
| #include <functional>
auto new_function = std::bind(function, arg1, arg2, ...);
|
function
:要绑定的函数或函数指针。
arg1, arg2, ...
:要绑定到函数的参数。
特点:
std::bind
可以绑定函数的部分或全部参数,从而创建一个新的可调用对象。
std::bind
返回的可调用对象可以被多次复制、传递和调用。
std::bind
可以绑定参数的位置,也可以绑定参数的值,还可以使用占位符 _1
、_2
等来表示未指定的参数。
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #include <iostream> #include <functional>
void greet(const std::string& name, int age) { std::cout << "Hello, " << name << "! You are " << age << " years old." << std::endl; }
int main() { auto greet_function = std::bind(greet, "Alice", std::placeholders::_1); greet_function(30);
auto add_function = std::bind(std::plus<int>(), std::placeholders::_1, std::placeholders::_2); std::cout << "Sum: " << add_function(3, 4) << std::endl;
return 0; }
|
在这个示例中,std::bind
函数用来创建一个新的可调用对象 greet_function
,它绑定了 greet
函数的第一个参数为 “Alice”,第二个参数由调用者传入。而另一个可调用对象 add_function
绑定了 std::plus<int>()
函数对象,表示对两个参数进行加法运算。
假设我们有一个事件循环,当某个定时器超时时,我们需要执行一个回调函数,并传递一些参数给这个回调函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| #include <iostream> #include <functional> #include <chrono> #include <thread>
void callback(const std::string& message, int value) { std::cout << message << ": " << value << std::endl; }
int main() { std::function<void()> func;
func = std::bind(callback, "Callback message", 42);
std::this_thread::sleep_for(std::chrono::seconds(2)); func();
return 0; }
|
function与bind的结合使用
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| #include <iostream> #include <functional>
void freeFunction(int a) { std::cout << "Free function called with " << a << std::endl; }
struct Functor { void operator()(int a) const { std::cout << "Functor called with " << a << std::endl; } };
class MyClass { public: void memberFunction(int a) { std::cout << "Member function called with " << a << std::endl; } };
int main() { std::function<void(int)> func1 = std::bind(freeFunction, std::placeholders::_1); func1(1);
Functor functor; std::function<void(int)> func2 = std::bind(functor, std::placeholders::_1); func2(2);
std::function<void(int)> func3 = [](int a) { std::cout << "Lambda called with " << a << std::endl; }; func3(3);
MyClass obj; std::function<void(int)> func4 = std::bind(&MyClass::memberFunction, &obj, std::placeholders::_1); func4(4);
return 0; }
|
占位符std::placeholders
用来表示未绑定的参数。这些占位符在 std::placeholders
命名空间中定义。常见的占位符有:
std::placeholders::_1
:表示调用时传递的第一个参数。
std::placeholders::_2
:表示调用时传递的第二个参数。
- 以此类推,可以使用
_3
, _4
….等表示更多的参数。
举个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| #include <iostream> #include <functional>
void exampleFunction(int a, int b, int c) { std::cout << "Called with a=" << a << ", b=" << b << ", c=" << c << std::endl; }
int main() { std::function<void(int)> boundFunction = std::bind(exampleFunction, std::placeholders::_1, 100, std::placeholders::_2);
boundFunction(10, 20);
return 0; }
|
1
| std::function<void(int)> boundFunction = std::bind(exampleFunction, std::placeholders::_1, 100, std::placeholders::_2);
|
这行代码创建了一个新的可调用对象 boundFunction
,它绑定了 exampleFunction
的第二个参数 b
为 100,而第一个参数 a
和第三个参数 c
使用占位符 _1
和 _2
,表示它们将在调用 boundFunction
时传递。