我刚开始学C++的时候似乎还没有lambda表达式这东西。这个blog的第一篇可见文章在2012年8月,还有一些更早的都是些垃圾水文被我删掉了,开设这个blog的时间我记得在学了web一段时间之后,在那之前我也在各种免费php空间搭过wordpress用过一段时间,后来废了。在更之前我还坚持用自己写的“佳佳空间”当blog用了很长一段时间(虽然后来终于还是放弃了,因为写得太垃圾)。推算下来可能要到9年多前了,大概就是小学的时候?反正是在2011年之前,而lambda表达式是C++11标准里的,所以那时候应该确实没有这东西。
好了回到正题。
C++的lambda表达式和js里的有点不一样,它可以自己选择是否打通函数范围之外的上下文,以使用外面的变量。还可以选择如何打通(引用外部变量和复制外部变量)。
lambda函数的结构长这样
[外部变量规则]{函数体}//没参数省略括号 [外部变量规则](参数){函数体}//省略返回类型指定 [外部变量规则](参数)->返回类型{函数体}//到C++11为止的完整形态
C++20又加了一个形式,暂时就不写在这了,毕竟2020年还没到呢不着急,而且也没编译器实现了。
[]
外部变量规则这个名字是我自己起的,这里面填的是如何使用函数体所在环境外的变量,什么都不填是不使用外部变量。
- & : 引用所有用到的外部变量
- = : 复制所有用到的外部变量
- &变量名: 指定要引用的变量
- =变量名 : 指定要复制的变量
- this : 把外层环境的this指针带进来
以上选项可以用逗号混合使用,至于哪些相斥看看也就明白了我就不写了。
参数,返回类型和函数体和原本的函数是一样的,不赘述了。
下面写了个例子,展示了引用参数和复制参数的区别,以及不同的简写形式。
#include <iostream> using namespace std; int main(int argc, char const *argv[]) { int t=1,d=2; cout<<"原t地址:"<<&t<<'\n'; cout<<"原d地址:"<<&d<<'\n'; auto fun1=[&](){cout<<"[&]"<<"t地址:"<<&t<<'\n';};//全部引用 auto fun2=[=](){cout<<"[=]"<<"t地址:"<<&t<<'\n';};//全部复制 auto fun3=[&t](){cout<<"[&t]"<<"t地址:"<<&t<<'\n';};//只引用t auto fun4=[t]{cout<<"[t]"<<"t地址:"<<&t<<'\n';};//只复制t。没有参数而省略括号的例子 auto fun5=[=,&t]()->void{cout<<"[=,&t]"<<"t地址:"<<&t<<' '<<"d地址:"<<&d<<'\n';};//引用t,其它复制。加上函数返回值(void)的例子 fun1(); fun2(); fun3(); fun4(); fun5(); return 0; }
结果
原t地址:0x7fff58ffdb2c 原d地址:0x7fff58ffdb28 [&]t地址:0x7fff58ffdb2c [=]t地址:0x7fff58ffdb18 [&t]t地址:0x7fff58ffdb2c [t]t地址:0x7fff58ffdb08 [=,&t]t地址:0x7fff58ffdb2c d地址:0x7fff58ffdb00
可以看到引用变量和外部变量是同一个地址,可以间接地说其实就是同一个变量。
复制参数的地址和外部的不同,也就是新开了一块内存把数据放进去用了,即复制了一份。
如果你使用的变量在函数里没有定义也没有对应的外部变量规则的话编译时会报错。
本文发布于 https://luojia.me
本站文章未经文下加注授权不得拷贝发布。