C++ 中std::function 、std::bind的使用和lambda的使用
- std::function是可调用对象的包装器;std::bind是将可点用对象和其参数一起进行绑定,且绑定后的结果可以使用std::function对象进行保存,并延迟调用到需要调用的时候;
- 在C++中,可调用实体主要包括函数,函数指针,函数引用,可以隐式转换为函数指定的对象,或者实现了opetator()的对象(即C++98中的functor)。C++0x中,新增加了一个std::function对象,std::function对象是对C++中现有的可调用实体的一种类型安全的包裹(我们知道像函数指针这类可调用实体,是类型不安全的)。
- bind是这样一种机制,它可以预先把指定可调用实体的某些参数绑定到已有的变量,产生一个新的可调用实体,这种机制在回调函数的使用过程中也颇为有用。C++98中,有两个函数bind1st和bind2nd,它们分别可以用来绑定functor的第一个和第二个参数,它们都是只可以绑定一个参数。各种限制,使得bind1st和bind2nd的可用性大大降低。C++0x中,提供了std::bind,它绑定的参数的个数不受限制,绑定的具体哪些参数也不受限制,由用户指定,这个bind才是真正意义上的绑定,有了它,bind1st和bind2nd就没啥用武之地了,因此C++0x中不推荐使用bind1st和bind2nd了,都是deprecated了。
-
C++11 的 lambda 表达式规范如下:
[
capture]
(
params)
mutable exception attribute->
ret{
body}
(1) [
capture]
(
params)
->
ret{
body}
(2) [
capture]
(
params)
{
body}
(3) [
capture]
{
body}
(4) 其中
- (1) 是完整的 lambda 表达式形式,
- (2) const 类型的 lambda 表达式,该类型的表达式不能改捕获("capture")列表中的值。
- (3)省略了返回值类型的 lambda 表达式,但是该 lambda 表达式的返回类型可以按照下列规则推演出来:
- 如果 lambda 代码块中包含了 return 语句,则该 lambda 表达式的返回类型由 return 语句的返回类型确定。
- 如果没有 return 语句,则类似 void f(...) 函数。
- 省略了参数列表,类似于无参函数 f()。
mutable 修饰符说明 lambda 表达式体内的代码可以修改被捕获的变量,并且可以访问被捕获对象的 non-const 方法。
exception 说明 lambda 表达式是否抛出异常(
noexcept
),以及抛出何种异常,类似于void f() throw(X, Y)。attribute 用来声明属性。
另外,capture 指定了在可见域范围内 lambda 表达式的代码内可见得外部变量的列表,具体解释如下:
-
[a,&b]
a变量以值的方式呗捕获,b以引用的方式被捕获。 -
[this]
以值的方式捕获 this 指针。 -
[&]
以引用的方式捕获所有的外部自动变量。 -
[=]
以值的方式捕获所有的外部自动变量。 -
[]
不捕获外部的任何变量。
此外,params 指定 lambda 表达式的参数。
- 测试用例:
1、std::function作为回调函数使用示例
class A { std::function<void()> callback_; public: A(const std::function<void()>& f) :callback_(f){} void Notify() { callback_(); } }; class Foo { public: void operator()(void) { std::cout << __FUNCTION__ << std::endl;//get the func name } }; void Test8() { Foo foo; A a(foo); a.Notify(); }
2、std::function 和std::bind 结合使用:
void call_when_event(int x, const std::function<void(int)>& func) { if (!(x & 1)) { //cout << x << endl; func(x); } } void call_when_event1(int x,int y, const std::function<void(int,int)>& func) { if (!(x & 1)) { //cout << x << endl; func(x,y); } } void output(int x) { cout << x << endl; } void output_add_2(int x,int y) { cout << x + y << endl; } void Test7() { auto fr = std::bind(output, std::placeholders::_1); for (int i = 0; i < 10; i++) { call_when_event(i, fr); } std::cout << std::endl; auto fr1 = std::bind(output_add_2, std::placeholders::_1,std::placeholders::_2); for (int i = 0; i < 10; i++) { call_when_event1(i, i,fr1); } }
3、lambda 测试用例:
返回vector中大于5小于10的元素的个数:
void Test5() { std::vector<int> coll; for (int i = 0; i <= 10; i++) { coll.push_back(i); } int count = std::count_if(coll.begin(), coll.end(), [](int x){return x > 5 && x < 10; }); std::cout << count << std::endl; }