C++ std::function和std::bind
##########################################################std::function
std::function<> 作用类似函数指针, 可以在以下几个场景:
(1). 绑定一个函数(普通函数或者静态函数)
#include <functional>
//普通函数
void func(void)
{
std::cout << __FUNCTION__ << std::endl;
}
//静态类成员函数
class Foo
{
public:
static int foo_func(int a)
{
std::cout << __FUNCTION__ << "(" << a << ") ->:" ;
return a;
}
};
int main(void)
{
std::function<void(void)> fr = func;
fr();
std::function<int(int)> fr1 = Foo::foo_func;
std::cout << fr1(456) << std::endl;
return 0;
}
(2). 实现回调函数
#include <functional>
class A
{
std::function<void()> callback_;
public:
A(const std::function<void()>& f) :callback_(f) {};
void notify(void)
{
callback_();
}
};
class Foo {
public:
void operator()(void)
{
std::cout << __FUNCTION__ << std::endl;
}
};
int main(void)
{
Foo foo;
A aa(foo);
aa.notify();
}
(3). 作为函数入参
#include <functional>
void call_when_even(int x, const std::function<void(int)>& f)
{
if (!(x & 1))
{
f(x);
}
}
void output(int x)
{
std::cout << x << " ";
}
int main(void)
{
for (int i = 0; i < 10; ++i)
{
call_when_even(i, output);
}
std::cout << std::endl;
}
(4). 作为函数返回值
typedef std::function<void()> func_t
void func(){}
func_t funcPtr()
{
func_t p = func;
return p;
}
itn main()
{
func_t pr; // 未初始化
func_t ppr = funcPtr; // 初始化
ppr();
return 0;
}
注意: 判断函数对象能不能使用时,使用std::function的operator bool()进行判断, 如果为true,证明改函数方法有效,否则无效(如果无效还继续使用的话, 会造成异常)
#######################################std::bind
std::bind函数看作一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表
std::bind将可调用对象与其参数一起进行绑定,绑定后的结果可以使用std::function保存。std::bind主要有以下两个作用:
(1). std::bind绑定普通函数
double my_divide (double x, double y) {return x/y;}
auto fn_half = std::bind (my_divide,_1,2); //绑定的结果用std::function保存
std::cout << fn_half(10) << '\n'; // 5
bind的第一个参数是函数名,普通函数做实参时,会隐式转换成函数指针。因此std::bind (my_divide,_1,2)等价于std::bind (&my_divide,_1,2);
_1表示占位符,位于<functional>中,std::placeholders::_1;
(2). std::bind绑定一个成员函数
struct Foo {
void print_sum(int n1, int n2)
{
std::cout << n1+n2 << '\n';
}
int data = 10;
};
int main()
{
Foo foo;
auto f = std::bind(&Foo::print_sum, &foo, 95, std::placeholders::_1);
f(5); // 100
}
bind绑定类成员函数时,第一个参数表示对象的成员函数的指针,第二个参数表示对象的地址。
必须显示的指定&Foo::print_sum,因为编译器不会将对象的成员函数隐式转换成函数指针,所以必须在Foo::print_sum前添加&;
使用对象成员函数的指针时,必须要知道该指针属于哪个对象,因此第二个参数为对象的地址 &foo;
(3). 绑定一个引用参数
默认情况下,bind的那些不是占位符的参数被拷贝到bind返回的可调用对象中。但是,与lambda类似,有时对有些绑定的参数希望以引用的方式传递,或是要绑定参数的类型无法拷贝。
(4). 指向成员函数的指针
#include <iostream>
struct Foo {
int value;
void f() { std::cout << "f(" << this->value << ")\n"; }
void g() { std::cout << "g(" << this->value << ")\n"; }
};
void apply(Foo* foo1, Foo* foo2, void (Foo::*fun)()) {
(foo1->*fun)(); // call fun on the object foo1
(foo2->*fun)(); // call fun on the object foo2
}
int main() {
Foo foo1{1};
Foo foo2{2};
apply(&foo1, &foo2, &Foo::f);
apply(&foo1, &foo2, &Foo::g);
}
成员函数指针的定义:void (Foo::*fun)(),调用是传递的实参: &Foo::f;
fun为类成员函数指针,所以调用是要通过解引用的方式获取成员函数*fun,即(foo1->*fun)();
bind的第一个参数是函数名,普通函数做实参时,会隐式转换成函数指针。因此std::bind (my_divide,_1,2)等价于std::bind (&my_divide,_1,2);
_1表示占位符,位于<functional>中,std::placeholders::_1;
(2). std::bind绑定一个成员函数
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性