C++11 lambda表达式
lambda表达式在很多其他高级语言(如,python等)中早已存在,c++11中也增加了对lambda表达式的支持。lambda表达式是一个匿名函数,可以作为函数来调用。其与普通的函数不同之处在于,lambda表达式本质上是一个表达式,可以像变量一样嵌入在其他任何表达式中间,而普通的函数只能先定义,无法将定义嵌入在其他表达式中。
c++完整的lambda表达式的声明形式如下:
[capture_list] (parameter_list) mutable exception -> return_type { body }
1, capture_list: 外部变量捕获列表;
2, parameter_list: 参数列表;
3, mutable: 指示是否可以修改捕获列表变量;
4, exception: 指示lambda表达式抛出的异常;
5, return_type: 指示lambda表达式的返回值类型;
6, body: lambda表达式函数体;
说明:
1,capture_list: 用于外部变量的捕获,默认情况下是赋值捕获(函数体中变量值的改变不会影响函数体外面的原始变量),如果在捕获变量前面加上&符号,表示引用捕获(函数体内变量值的改变会影响函数体外面的原始变量):
int a = 10;
int b = 20;
[a, b]()mutable->int{a = 40; return a + b;}();
std::cout << "a=" << a << " b=" << b << std::endl; //赋值捕获,a=10
[&a, b]()mutable->int{a = 50; return a + b;}();
std::cout << "a=" << a << " b=" << b << std::endl; //引用捕获,a=50
除此之外,还有个隐式捕获。当lambda表达式函数体中引用的变量没有局部定义,也不在参数列表和捕获列表中时,编译器会报类似 xxx is not captured错误。当我们修改捕获列表为[=]时,编译器会隐式地赋值捕获表达式函数体中的变量,当我们修改捕获列表为[&]时,编译器会隐式地引用捕获表达式函数体中的变量:
int a = 10;
int b = 20;
[=]()mutable->int{a = 40; return a + b;}();
std::cout << "a=" << a << " b=" << b << std::endl; // 隐式赋值捕获a和b, a=10
[&]()mutable->int{a = 50; return a + b;}();
std::cout << "a=" << a << " b=" << b << std::endl; // 隐式引用捕获a和b, a=50
2, parameter_list: 类似于普通函数,lambda表达式参数列表提供调用时参数传递。参数列表支持默认参数。
3,mutable: 默认情况下,如果没有增加这个关键字,捕获列表中的变量是只读的,不可以在lambda函数体中被修改:
auto func1 = [a, b]()mutable->int{a = 40; return a + b;}; // ok
auto func2 = [a, b]()->int{a = 40; return a + b;}; // a是只读的,不能被修改
4, 完整表达式在某些情况下可以简写。
(1)当没有参数列表的时候,可以省略();
(2)当返回类型可以推导出来(如果lambda函数体含有return语句,可以推导出返回类型;当没有return语句时,默认返回void)时,也可以省略返回类型;
std::cout << typeid([]{int a = 10; std::string b = "hello"; a;}()).name() << std::endl; // 输出v
(3)当省略 () -> return_type三者中的任意一个时,三个都必须同事省略。即,() -> return_type要么同时存在,要么同时省略。
相关推荐
f = lambda x, y, z: x + y + z # returns a function that can optionally be assigned a name. def func: