C++ lambda表达式
一、lambda表达式
(1) lambda表达式的一般形式: [ capture list ] ( parameter list ) -> return type { function body }
其中参数列表和返回类型可以省略,但必须永远包含捕获列表和函数体 。比如:
auto f = [] { return 42; }
注意:在忽略返回类型的情况下,如果函数体只有一条return语句,则返回类型从返回的表达式的类型推断出来;
如果一个函数体包含任何除return意外的语句,编译器都将返回类型推断为void。
(2) 一个lambda只有在其捕获列表中捕获一个它所在函数中的局部变量,才能在函数体中使用该变量。
1 //错误: sz未捕获 2 int sz = 2; 3 auto f = [] (const string &a) { return a.size() >= sz; };
注意:捕获列表只用于局部非static变量,lambda可以直接使用局部static变量和它所在函数之外声明的名字(全局变量)。
1 int main() 2 { 3 //正确,sz为static变量 4 static int sz = 2; 5 auto f = [] (const string &a) { return a.size() >= sz; }; 6 return 0; 7 } 8 int sz = 2; 9 int main() 10 { 11 //正确,sz为全局变量 12 auto f = [] (const string &a) { return a.size() >= sz; }; 13 return 0; 14 }
(3) 被捕获的变量的值是在lambda创建时拷贝,而不是调用时拷贝。
1 int main() 2 { 3 int a = 42; 4 auto f = [a] { return a; }; 5 a = 0; 6 cout << f() << ',' << a; //f保存的时我们创建它时a的拷贝 7 return 0; //所以此处的输出为42,0 8 }
(4) 隐式捕获
1 int main() 2 { 3 int a = 42; //=表示采用值捕获的方式进行隐式捕获,&表示采用引用捕获的方式进行隐式捕获 4 auto f = [=] { return a; }; //隐式捕获a 5 a = 0; 6 cout << f() << ',' << a; 7 return 0; 8 }
(5) 可变lambda:当我们要改变捕获变量的值的时候,必须在参数列表后加上关键字mutable,参数列表里面的参数可以省略,但是括号不能省略!
1 int main() 2 { 3 int a = 42; 4 auto f = [a] () mutable { return ++a; }; //此时参数列表()不能省略! 5 cout << f() << ',' << a; //输出为43,42 6 7 8 auto g = [&a] () mutable { return ++a; }; 9 cout << g() << ',' << a; //输出还是43,42 ;a的值(引用)并未修改,因为cout的嵌套使用出现了问题 10 11 cout << g() << endl; 12 cout << a; //此时输出为43,43。因为此时cout的调用未出错 13 return 0; 14 }
cout << g( ) << ',' << a ; 结果出错的原因:
这和lambda表达式无关,而和cout的嵌套调用有关。cout的嵌套出了问题,使得结果未定义
cout<<g()<<a相当于operator<<的嵌套调用:operator<<(operator<<(cout, g()), a),而g()中又对a的值做了有副作用的修改,因此,这是一个未定义行为,因为C++中没有规定函数参数的求值顺序,结果取决于编译器实现。如果编译器从右向左求值,那么两个参数将分别求值得到43, 42,这是VC++和gcc的实现方式;如果编译器从左向右求值,那么两个参数将分别求值得到43, 43。两种结果都符合C++规范。这和lambda表达式无关,而和cout的嵌套调用有关。
总结:当其中一个输出的变量a会对另一个输出的变量b的值产生影响的时候,不应在同一条cout语句中同时输出a和b,而应该将它们分别在两条cout语句中输出,这样可以避免出错。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南