1. 关于std::function()
在C语言的时代,我们可以使用函数指针来吧一个函数作为参数传递,这样我们就可以实现回调函数的机制。到了C++11以后在标准库里引入了std::function模板类,这个模板概括了函数指针的概念
函数指针只能指向一个函数,而std::function对象可以代表任何可以调用的对象,比如说任何可以被当作函数一样调用的对象。
当你创建一个函数指针的时候,你必须定义这个函数签名(表征这个函数的入参,返回值等信息);同样的,当你创建一个std::function对象的时候,你也必须指定它所代表的可调用对象的函数签名。这一点可以通过std::function的模板参数来实现。
举个例子来说,如果要定义一个std::function对象func,这个对象可以表示任何有如下函数签名的可调用对象的,
bool(const std::unique_ptr<Widget>)&, // C++11里面用来比较两个
const std::unique_ptr<Widget>&) //std::unique_ptr<Widget>对象的函数签名
你可以这么写,
std::function<bool(const std::unique_ptr<Widget>&,
const std::unique_ptr<Widget>&)> func;
这是因为lambda表达式产生了可调用的对象,这个对象这里称做一个闭包(closure),可以保存在std::function对象里面。
closure(闭包)的定义是,一个函数和它所引用的非本地变量(非lambda表达式内部定义的变量)的一个集合。
2. 使用std::function作为函数入参
2.1 基于传值的方式传递参数
参看下面一段代码,实现了一个注册回调函数的机制,
#include <fonctional>
void registerCallBack(std::function<void()>);
入参std::function<void()>是一个模板类对象,它可以用一个函数签名为void()的可调用对象来进行初始化;上述实现里面是一个传值调用。我们来看一下它的调用过程,
// 方法(A)
registerCallBack([=]{
.... // 回调函数的实现部分
})
这里使用了lambda表达式作为函数的入参,正如前面所说的lambda表达式会生成一个匿名的闭包(closure),基于这个闭包构造了一个std::function<void()>的对象,然后通过传值调用的方式把这个对象传递registerCallBack函数中使用。
3.常规使用(回调)
void fun1()
{
std::cout << "this is fun1" << endl;
}
int fun2(int a)
{
std::cout << "this is fun2" << endl;
return 0;
}
std::vector<int>& fun3(int a)
{
vector<int> data;
std::cout << "this is fun3" << endl;
return data;
}
std::function<void()> FUN1 = fun1;
FUN1();
std::function<int(int)> FUN2 = fun2;
FUN2(1);
std::function<std::vector<int>(int)> FUN3 = fun3;
FUN3(2);
输出如下