C++ function与bind
std::function:
-
可调用对象:
是一个函数指针
是一个具有 operator()成员函数的类对象(传说中的仿函数),lambda 表达式
是一个可被转换为函数指针的类对象
是一个类成员(函数)指针
bind 表达式或其它函数对象 -
而 std::function 就是上面这种可调用对象的封装器,可以把 std::function 看做一个函数对象,用于表示函数这个抽象概念。
-
std::function 的实例可以存储、复制和调用任何可调用对象,存储的可调用对象称为 std::function 的目标
-
若 std::function 不含目标,则称它为空,调用空的 std::function 的目标会抛出 std::bad_function_call 异常。
-
std::function常用于函数回调
#include <iostream>
#include <functional>
using namespace std;
struct Foo {
Foo(int num) : num_(num) {}
void print_add(int i) const{
cout << num_ + i << endl;
}
int num_;
};
struct PrintNum {
void operator()(int i) const {
cout << i << "\n";
}
};
void print_num(int i) {
cout << i << "\n";
}
int main() {
// 存储自由函数
std::function<void(int)> f_display = print_num;
f_display(-9);
// 存储lambda
std::function<void()> f_display_42 = []() { print_num(42); };
f_display_42();
// 存储到 std::bind 调用结果
std::function<void()> f_display_31337 = std::bind(print_num, 31337);
f_display_31337();
// 存储成员函数的调用
std::function<void(const Foo&, int)> f_add_display = &Foo::print_add;
const Foo foo(314159);
f_add_display(foo, 1);
f_add_display(314159, 1);
// 存储类数据成员访问器的调用
std::function<int(Foo const&)> f_num = &Foo::num_;
cout << "num_: " << f_num(foo) << endl;
// 存储成员函数及对象的调用
using std::placeholders::_1;
std::function<void(int)> f_add_display2 = std::bind(&Foo::print_add, foo, _1);
f_add_display2(2);
// 存储数据成员函数和对象指针的调用
std::function<void(int)>f_add_display3 = std::bind(&Foo::print_add, &foo, _1);
f_add_display3(3);
// 存储到函数对象的调用
std::function<void(int)> f_add_display_obj = PrintNum();
f_add_display_obj(18);
return 0;
}
std::bind:
-
使用 std::bind 可以将可调用对象和参数一起绑定,绑定后的结果使用 std::function 进行保存,并延迟调用到任何我们需要的时候。*
-
std::bind 通常有两大作用:*
-
可调用对象与参数一起绑定为另一个 std::function 供调用*
-
将 n 元可调用对象转成 m(m < n)元可调用对象,绑定一部分参数,这里需要使用 std::placeholders*
-
#include <iostream>
#include <functional>
#include <memory>
using namespace std;
struct Foo {
void print_sum(int n1, int n2) {
cout << n1 + n2 << endl;
}
int data = 10;
};
void f(int n1, int n2, int n3, const int& n4, int n5) {
cout << n1 << ' ' << n2 << ' ' << n3 << ' ' << n4 << ' ' << n5 << endl;
}
int g(int n) { return 0; }
int main() {
// 针对 _1, _2, _3... 用作参数占位,延时输入参数
using namespace std::placeholders;
// 演示参数重排序和按引用传递
int n = 7;
// (_1 与 _2 来自 std::placeholders, 并表示将来会传递给 f1 参数)
auto f1 = std::bind(f, _2, 42, _1, std::cref(n), n);
n = 10;
// 1 为 _1 所绑定,2 为 _2 所绑定,不使用 1001
// 进行到 f(2, 42, 1, n, 7)
f1(1, 2, 1001);
// 嵌套 bind 子表达式共享占位符
auto f2 = std::bind(f, _3, std::bind(g, _3), _3, 4, 5);
// 进行到 f(12, g(12), 12, 4, 5); 的调用
f2(10, 11, 12);
// 绑定指向成员函数指针
Foo foo;
auto f3 = std::bind(&Foo::print_sum, &foo, 95, _1);
f3(5);
// 绑定指向数据成员指针
auto f4 = std::bind(&Foo::data, _1);
cout << f4(foo) << endl;
// 智能指针亦能用于调用被引用对象的成员
cout << f4(std::make_shared<Foo>(foo)) << endl;
return 0;
}