c++11 lamdba详解
一、 语法
[capture] (parameters) mutable ->return_type{statement}
1、 [capture] 捕获列表: 捕捉列表总是出现在lamdba函数的开始处。事实上,[]是lambda引出符。编译器根据该引出符判断接下来的代码是否是lambda函数。
捕获类型 | 说明 |
---|---|
[var] | 值传递方式捕捉变量var |
[=] | 值传递方式捕捉所有父作用域的变量(包括this) |
[&var] | 引用传递捕捉变量var |
[&] | 引用传递捕捉所有父作用域的变量(包括this) |
[this] | 值传递方式捕捉当前的this指针 |
2、 (parameters) 参数列表: 和函数的参数列表一致。如果不需要参数列表,则可以连同括号()一起省略。
3、 mutable:mutable 修饰符。 默认情况下,lamdba捕获的变量都是const的,要想在lamdba的函数体里修改通过值捕获的变量,需要使用mutable修饰符。
4、 -> return_type: 返回类型,不需要返回值的时候可以连同符合->一起省略。
5、 {statement}: 函数体,内容与普通函数一样,不过除了可以使用参数之外,还可以使用所有捕获的变量。
二、 实例
实例1、 以值捕获a
void test1() {
int a = 3;
[a]()->int{ return a + 4; }();
[a]()->int{ return ++a; }(); // error,因为以值捕获a,捕获的变量a在lamdba里是const的,所以不能修改a的值
[a]() mutable -> int {return ++a;}(); // ok, 通过mutable修饰符之后,可以修改a的值了。这里要注意a的值,执行完lamdba表达式后,a=3,原因见实例2.
}
实例2、 以值捕获a,详解捕获的时机
void test2_1(){
int a = 3;
auto f = [a]()->int{return a+3;};
a = 100;
auto b = f(); // b为6,lamdba捕获的时机是lamdba被创建时,当lamdba被创建时,a=3,所以b=3+3=6
};
void test2_2(){
int a = 3;
auto f = [a]()mutable->int{return ++a;};
a = 100;
auto b = f(); // b为4,原因见test2_1(), 此时a的值为100. 你可能会疑惑为什么a的值是100? 原因见下面
};
个人认为lamdba值捕获的变量,就好像是在lamdba的实现体里定义了一个同名的变量,且是const。如下:
auto f = [a]()mutable->int{return ++a;};
相当于:
auto f = []()mutable->int{const int a = 3; return ++a;}; // 按照这种理解,你应该可以理解test2_1和test2_2的b和a的值了
实例3: 以引用捕获a
void test3() {
int a = 3;
auto f = [&a]()->int{return ++a;};
a = 100;
auto b = f(); // b=101, a=101 不用怀疑,就是101,如果不知道为什么,想想引用的意义就能理解了
}