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要么同时存在,要么同时省略。

C++11 lambda表达式

相关推荐