c/c++ lambda 表达式使用实例讲解
lambda 表达式 剖析大前提:捕获列表里变量的确定时机。捕获列表和参数列表有区别,捕获列表里的变量,是在捕获的时间点就确定了,而不是在lambda调用时确定,参数列表是在调用时才确定。所以当捕获了一个int i,i=12,然后在lambda后面的代码又改变i为22,但是当调用lambda的时候,i值还是12。剖析点:1,值捕获,即使在lambda后面改变了该值,在调用lambda时,这个值还是捕获时的值。2,引用捕获,在lambda后面改变了该值,在调用lambda时,这个值不是捕获时的值,而是改变后的值。3,隐式捕获:[=]代表全部采用值捕获 [&]代表全部采用引用捕获 [=,&val]代表val为引用捕获,其余为值捕获 [&,val]代表val为值捕获,其余为引用捕获 4,可变lambda,当想在lambda函数体里,修改一个值捕获的变量是,需要mutable关键字。5,lambda的返回类型,函数体是单一的return语句的话,可以在声明lambda时,省略返回值的类型。由剖析点2:引用捕获,会引发很多血案。比如,被捕获的引用或者指针指向的对象已经不存在了,然后调用lambda时,就会出现致命错误。警告:当以引用或者指针方式捕获一个变量时,必须保证在lambda执行时变量是存在的。建议:1,捕获一个普通变量时,如int,string或其他非指针类型,通常可以采用简单的值捕获方式。所以,只需关注变量在捕获时,值是否是所需的值就行。2,如果捕获一个指针或迭代器,或引用,就必须保证在lambda被执行的时候,绑定到迭代器,指针或引用的对象仍然存在,而且,需要保证对象是预期的值。因为,有可能在捕获的时候,是预期的值,但是在执行lambda之前有代码改变了绑定对象的值,在执行lambda时,就变成不是预期的值了。3,一般来说,尽量减少捕获的数据量,来避免潜在的捕获导致的问题。而且,如果可能的话,尽量避免捕获指针或引用。#include #include #include using namespace std; int main(){ //test1 值捕获 /* int i = 1; auto f = [i]{return i;}; i = 10; int j = f(); cout << j << endl; */ //test2 引用捕获 /* int i = 1; auto f = [&i]{return i;}; i = 10; int j = f(); cout << j << endl;//3 */ //test3 隐式值捕获 /* int i = 1; int j = 2; auto f = [=]{return i + j;}; i = 3; int m = f(); cout << m << endl; */ //test4 隐式引用捕获 /* int i = 1; int j = 2; auto f = [&]{return i + j;}; i = 3; int m = f(); cout << m << endl;//5 */ //test5 隐式,显式混合1 /* int i = 1; int j = 2; //i为值捕获,j为引用捕获 auto f = [=,&j]{return i + j;}; i = 3; int m = f(); cout << m << endl;//3 */ //test5 隐式,显式混合2 /* int i = 1; int j = 2; //i为引用捕获,j为值捕获 auto f = [&,j]{return i + j;}; i = 3; int m = f(); cout << m << endl;//5 */ //test6 可变lambda /* int i = 10; auto f = [i] () mutable{return ++i;}; int j = f(); cout << j << endl; */ /* const int i = 10; //编译错误,因为i为const auto f = [i] () mutable{return ++i;}; int j = f(); cout << j << endl; */ //test7 lambda的返回类型 vector //改变ivec里的值,负数变成整数 //此lambda不写返回类型没有问题. //transform(ivec.begin(),ivec.end(),ivec.begin(), // [](int i){return i < 0 ? -i : i;}); //此lambda不写返回类型也没有问题. transform(ivec.begin(), [](int i){if(i < 0) return -i; else return i;}); for(const auto &s : ivec){ cout << s << " "; } cout << endl; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |