Lambda
Lambda 表达式,实际上就是提供了一个类似匿名函数的特性
Lambda 表达式的基本语法如下:
[capture_list] (params_list) mutable exception -> return type { function body }
capture__list:捕获外部变量列表,方式包括=,&,this等,不可省略。
params_list:形参列表,无参数可省略。
mutable:指示符,用来说明是否可以修改捕获的变量,因为Lambda默认是const属性。
exception:异常设定,可以用于指定函数抛出的异常。
return type:返回类型。
function:函数体。
捕获类型如下:
- []:默认不捕获任何变量;
- [=]:将Lambda表达式所在范围内的所有可见局部变量按值传递,即在函数体内都可使用。;
- [&]:将Lambda表达式所在范围内的所有可见局部变量按引用传递,即在函数体内都可使用。;
- [x]:仅以值传递捕获x,其它变量不捕获,无法对x进行修改,因为默认下x是const类型,需要mutable指示符的介入;
- [x...]:以包展开方式值传递捕获参数包变量;
- [&x]:仅以引用捕获x,其它变量不捕获;
- [&x...]:以包展开方式引用捕获参数包变量;
- [=, &x]:默认以值传递捕获所有变量,但是x是例外,通过引用捕获;
- [&, x]:默认以引用捕获所有变量,但是x是例外,通过值传递捕获;
- [this]:通过引用捕获当前对象(其实是复制指针);
- [*this]:通过值传递方式捕获当前对象;
int main()
{int x = 10;
int y = 20;
auto print = [](int s) {std::cout << "value is " << s << std::endl;};
auto lambAdd = [x](int a) {
// x++; 此处复制捕获,x是只读,不允许自增,编译会报错
return a + x;
};
auto lambAdd2 = [&x](int a, int b) {
x = x+5; //引用捕获,可以改变x
return a + b + x;
};
auto iSum = lambAdd(10);
auto iSum2 = lambAdd2(10, 11);
print(iSum);
print(iSum2);
return 0;
}
mutable
从代码可以看出,复制捕获不允许修改变量值,而引用捕获则允许修改变量值。那么如果我想使用复制捕获,又想修改变量的值呢,这时我们就想起来有个关键字,叫做mutable,它允许在常成员函数中修改成员变量的值,
mutable可以取消Lambda的常量属性,因为Lambda默认是const属性;multable仅是让Lamdba函数体修改值传递的变量,但修改后并不影响外部的变量。
所以我们可以给lambda表达式指定mutable关键字,如下:
int main()
{
int x = 10;
int y = 20;
auto print = [](int s) {std::cout << "value is " << s << std::endl;};
auto lambAdd = [x](int a) mutable {
x++;//允许x被修改
return a + x;
};
auto iSum = lambAdd(10);
print(iSum);
print(x);
return 0;
}
执行结果如下:
value is 21
value is 10
所以加上mutable以后就可以对复制捕获进行修改,但有一点,它的修改出了lambda表达式以后就无效了。
1. 值捕获与参数传值类似,值捕获的前提是变量可以拷贝,不同之处则在于,被捕获的变量在Lambda表达式被创建时拷贝,而非调用时才拷贝:
void lambda_value_capture() {
int value = 1;
auto copy_value = [value] { //表达式被创建
return value;
};
value = 100;
auto stored_value = copy_value();
std::cout << "stored_value = " << stored_value << std::endl;// 这时, stored_value == 1, 而value == 100. 因为copy_value 在创建时就保存了一份value 的拷贝
}
2. 引用捕获与引用传参类似,引用捕获保存的是引用,值会发生变化。
void lambda_reference_capture() {
int value = 1;
auto copy_value = [&value] {
return value;
};
value = 100;
auto stored_value = copy_value();
std::cout << "stored_value = " << stored_value << std::endl; // 这时, stored_value == 100, value == 100. 因为copy_value 保存的是引用
}
lambda表达式赋值
不能用一个lambda表达式给另外一个赋值,但可以进行初始化拷贝。
int main()
{
auto a = [] { cout << "A" << endl; };
auto b = [] { cout << "B" << endl; };
//a = b; // 非法,lambda无法赋值
auto c(a); // 合法,生成一个副本
return 0;
}
exception
exception 声明用于指定函数抛出的异常,如抛出整数类型的异常,可以使用 throw(int)。(没有找到代码实例)