山东建大建设有限公司网站,wordpress主题添加中文版,优化产品,东莞网站建设公司电话第17.1节 匿名函数的基本语法
[捕获列表](参数列表) mutable(可选) 异常属性 - 返回类型 {
// 函数体
}语法规则#xff1a;lambda表达式可以看成是一般函数的函数名被略去#xff0c;返回值使用了一个 - 的形式表示。唯一与普通函数不同的是增加了“捕获列表”。
…
第17.1节 匿名函数的基本语法
[捕获列表](参数列表) mutable(可选) 异常属性 - 返回类型 {
// 函数体
}语法规则lambda表达式可以看成是一般函数的函数名被略去返回值使用了一个 - 的形式表示。唯一与普通函数不同的是增加了“捕获列表”。
//[捕获列表](参数列表)-返回类型{函数体}
int main()
{auto Add [](int a, int b)-int {return a b;};std::cout Add(1, 2) std::endl; //输出3return 0;
}一般情况下编译器可以自动推断出lambda表达式的返回类型所以我们可以不指定返回类型即
//[捕获列表](参数列表){函数体}
int main()
{auto Add [](int a, int b) {return a b;};std::cout Add(1, 2) std::endl; //输出3return 0;
}但是如果函数体内有多个return语句时编译器无法自动推断出返回类型此时必须指定返回类型。
第17.2节 捕获列表
有时候需要在匿名函数内使用外部变量所以用捕获列表来传递参数。根据传递参数的行为捕获列表可分为以下几种
值捕获
与参数传值类似值捕获的前提是变量可以拷贝不同之处则在于被捕获的变量在 lambda表达式被创建时拷贝而非调用时才拷贝
void test3()
{cout test3 endl;int c 12;int d 30;auto Add [c, d](int a, int b)-int {cout d d endl;return c;};d 20;std::cout Add(1, 2) std::endl;
}引用捕获
与引用传参类似引用捕获保存的是引用值会发生变化。如果Add中加入一句c a;
void test5()
{cout test5 endl;int c 12;int d 30;auto Add [c, d](int a, int b)-int {c a; // 编译对的cout d d endl;return c;};d 20;std::cout Add(1, 2) std::endl;
}隐式捕获
手动书写捕获列表有时候是非常复杂的这种机械性的工作可以交给编译器来处理这时候可以在捕获列表中写一个 或 向编译器声明采用引用捕获或者值捕获。
void test7()
{cout test7 endl;int c 12;int d 30;// 把捕获列表的改成再测试auto Add [](int a, int b)-int {c a; // 编译对的cout d d endl;return c;};d 20;std::cout Add(1, 2) std::endl;std::cout c: c std::endl;
}空捕获列表
捕获列表’[]中为空表示Lambda不能使用所在函数中的变量。
void test8()
{cout test7 endl;int c 12;int d 30;// 把捕获列表的改成再测试// [] 空值不能使用外面的变量// [] 传值lambda外部的变量都能使用// [] 传引用值lambda外部的变量都能使用auto Add [](int a, int b)-int {cout d d endl; // 如果捕获列表为[],则编译报错return c;// 如果捕获列表为[],则编译报错};d 20;std::cout Add(1, 2) std::endl;std::cout c: c std::endl;
}运行结果
表达式捕获
上面提到的值捕获、引用捕获都是已经在外层作用域声明的变量因此这些捕获方式捕获的均为左值而不能捕获右值。C14之后支持捕获右值允许捕获的成员用任意的表达式进行初始化被声明的捕获变量类型会根据表达式进行判断判断方式与使用 auto 本质上是相同的
void test9()
{cout test9 endl;auto important std::make_uniqueint(1);auto add [v1 1, v2 std::move(important)](int x, int y) - int {return x y v1 (*v2);};std::cout add(3,4) std::endl;
}泛型 Lambda
在C14之前lambda表示的形参只能指定具体的类型没法泛型化。从 C14 开始 Lambda 函数的形式参数可以使用** auto关键字来产生意义上的泛型**
//泛型 Lambda C14
void test10()
{cout test10 endl;auto add [](auto x, auto y) {return xy;};std::cout add(1, 2) std::endl;std::cout add(1.1, 1.2) std::endl;
}可变lambda
采用值捕获的方式lambda不能修改其值如果想要修改使用mutable修饰采用引用捕获的方式lambda可以直接修改其值
void test12() {cout test12 endl;int v 5;// 值捕获方式使用mutable修饰可以改变捕获的变量值auto ff [v]() mutable {return v;};v 0;auto j ff(); // j为6
}void test13() {cout test13 endl;int v 5;// 采用引用捕获方式可以直接修改变量值auto ff [v] {return v;};v 0;auto j ff(); // v引用已修改j为1
}第17.3节 总结
如果捕获列表为[]则表示所有的外部变量都按引用传递给lambda使用如果捕获列表为[]则表示所有的外部变量都按值传递给lambda使用匿名函数构建的时候对于按值传递的捕获列表会立即将当前可以取到的值拷贝一份作为常数然后将该常数作为参数传递。
Lambda捕获列表总结
[]空捕获列表Lambda不能使用所在函数中的变量。[names]names是一个逗号分隔的名字列表这些名字都是Lambda所在函数的局部变量。默认情况下这些变量会被拷贝然后按值传递名字前面如果使用了则按引用传递[]隐式捕获列表Lambda体内使用的局部变量都按引用方式传递[]隐式捕获列表Lanbda体内使用的局部变量都按值传递[,identifier_list]identifier_list是一个逗号分隔的列表包含0个或多个来自所在函数的变量这些变量采用值捕获的方式其他变量则被隐式捕获采用引用方式传递identifier_list中的名字前面不能使用。[,identifier_list]identifier_list中的变量采用引用方式捕获而被隐式捕获的变量都采用按值传递的方式捕获。identifier_list中的名字不能包含this且这些名字面前必须使用。