C++ lambda表达式的使用
lambda语法如下:
[函数对象参数](操作符重载函数参数) mutable 或 exception 声明 -> 返回值类型 {函数体}
[函数对象参数]
函数对象是传递给编译器自动生成的函数对象类的构造函数的。函数对象参数只能使用那些定义lambda表达式时,作用域内可见的局部变量。这部分不可省略。
[] 没有任何函数对象参数。
[=] 函数体可以使用可见的所有局部变量,按值传递。
[&] 函数体可以使用可见的所有局部变量,按引用传递。
[this] 函数体可以使用lambda所在类中的成员变量。
[a] 函数体可以使用变量a,按值传递。但函数体内不能修改传递进来的a的拷贝,因为默认情况下函数是const的,要修改传递进来的拷贝,可以添加mutable修饰符。
[&a] 函数体可以使用变量a,按引用传递。
[a, &b] 函数体可以使用变量a和b,其中a按值传递,b按引用传递。
[=, &a] 除a按引用传递外,其它参数按值传递。
[&, a] 除a按值传递外,其它参数按引用传递。
c++14中增加了初始化捕获将对象移动入闭包的特性:
auto func = [obj = std::move(obj)]{...};
位于“=”左侧的,是指定的闭包类成员变量的名字,而位于其右侧的则是其初始化表达式。需要注意的是“=”的左右两侧处于不同的作用域。左侧作用域就是闭包类的作用域,而右侧的作用域则与lambda式加以定义之处的作用域相同。
(操作符重载函数参数)
标识重载的()操作符的参数,没有参数时,可以省略。
mutable或exception
这部分可以省略。按值传递函数对象参数,加上mutable修饰符后,可以修饰传递进来的拷贝。exception声明用于指定函数抛出的异常。
->返会类型
当编译器可以自动推断出返回值类型时,这部分可以省略。
{函数体}
标识函数的实现,这部分不能省略,但函数体可以为空。
示例
extern "C"{
int printf(const char * format, ...);
}
int main(){
int a = 520;
auto show = [=](){printf("Val = %d\n", a);};
show();
a = 521;
show();
return 0;
}
输出为:
Val = 520
Val = 520
extern "C"{
int printf(const char * format, ...);
}
int main(){
int a = 520;
auto show = [&](){printf("Val = %d\n", a);};
show();
a = 521;
show();
return 0;
}
输出为:
Val = 520
Val = 521