C++11之Lambda与bind

Lambda语法和stl::bind 都是语法糖,但不得不说它们的作用很出色:
1. 更方便的定义匿名函数
2. 更简洁的代码逻辑
3. 更安全的私有函数

这称之为closure,即闭包.

Lambda

表达式语法有如下五种形式:

[capture](parameters) mutable throw() ->return_type {body}
[capture](parameters) mutable ->return_type {body}
[capture](parameters) ->return_type {body}
[capture](parameters) {body}
[capture] {body}

capture

[]用于标识一个lambda的开始,其中可以存在零个或多个捕获参数,用逗号分隔.并且只允许以下两种标识符表示:

  • & 引用值

  • = 拷贝值

对于参数的形式可以有:

1. [] 空.即不任何参数
2. [=]. 即以值拷贝形式导入所有成员.
3. [&]. 即以引用形式导入所有成员.
4. [this]. 即以引用形式导入当前对象的所有成员.
5. [var1]. 即值拷贝形式导入var1,导入多个以逗号分隔.
6. [&var1].即引用形式导入var1,导入多个以逗号分隔.
5. [&,var2].即var2成员使用值拷贝,其他成员引用,导入多个以逗号分隔.
6. [=,&var2].即var2成员使用引用,其他成员值拷贝,导入多个以逗号分隔.

parameters

这个部分没有参数时,可以省略.参数可以有多个,以逗号分割,通过值拷贝或引用方式传递,如:

[](int var1){}
[](int &var1,int var2){}

mutable

mutable为一个修饰符,可以省略.代表 lambda 表达式体内的代码可以修改被捕获的变量,并且可以访问被捕获对象的 non-const 方法.若在lambda中使用了mutable修饰符,则(parameters)部分是不可省略掉的,即使不为空.

throw()

代表 lambda 表达式是否抛出异常,以及抛出何种异常,可以省略.

return-type

->return-type,返回值类型.主要目的是用来追踪lambda函数(有返回值情况下)的返回类型。若lambda函数不需要返回值,则可以省略掉这部分.

stl::bind

std::bind它可以预先把指定可调用实体的某些参数绑定到已有的变量,产生一个新的可调用实体,这种机制在回调函数的使用过程中也颇为有用.

C++98中,有两个函数bind1stbind2nd,它们分别可以用来绑定闭包函数的第一个和第二个参数,但它们都是只可以绑定一个参数,各种限制,使得bind1stbind2nd的可用性大大降低。

在C++11中提供的std::bind它绑定的参数的个数不受限制,绑定的具体哪些参数也不受限制,由用户指定,这个bind才是真正意义上的绑定。

std::bind的基本语法:

#include <iostream>
#include <functional>
using namespace std;

int func(int tmp, int round)
{
    return tmp + round;
}

int main()
{
    using namespace std::placeholders;    // _1 占位符

    int round = 2;
    std::function<int(int)> f = std::bind(func, _1, round);
    cout << "result = " << f(1) << endl;


    return 0;
}