c++ lambda表达式作用_c++基础语法

(101) 2024-06-13 16:01:01

文章目录

  • 前言
  • lambda的基本形式
  • lambda中的捕获列表[ ]的常用方式
  • lambda表达式中mutable关键字
  • lambda作为形参传参的用法

前言

对于Lambda表达式:其实本质就是一个函数,其用法也和函数差不多,只不过它和函数的区别在于,lambda表达式可以在函数里面定义,而函数不可以嵌套定义,并且在形式上也有一定的区别;
一般我们把lambba表达式,当作一种匿名函数去使用,也就是说:这个函数是没有名称的;


lambda的基本形式

基本形式如下:
[捕获列表](参数列表)->返回类型{函数体};

int main() { 
    []{ 
    cout<<"这是最基本的lambda表达式的形式"}; return 0; } 

lambda表达式的参数列表如果没有,那么就可以省略;
返回值如果没有也可以省略,甚至有时候返回值类型很简单,编译器也会自动推到出,意思是你可以省略;

c++ lambda表达式作用_c++基础语法 (https://mushiming.com/)  第1张


说:lambda表达式和函数基本没什么区别,还说时匿名函数,那么我们就尝试以下用函数指针形式去调用;

int main { 
    void(* p)() = [ ]{ 
    cout<<"用函数指针形式调用lambda表达式"<<endl; }; p(); //调用lambda表达式 return 0; } 

测试:调用成功;
c++ lambda表达式作用_c++基础语法 (https://mushiming.com/)  第2张


当然:还可以结合auto去推到lambda表达式的类型;

int main { 
    auto p = [ ]{ 
    cout<<"用函数指针形式调用lambda表达式"<<endl; }; p(); //调用lambda表达式 return 0; } 

省略形参参数,省却返回值的lambda表达式写法

 //一个无返回值类型,无参数类型的函数  void fun (){ 
    //函数体逻辑实现 } //以下三种lambada表达式都等价这个函数模样 //1. [ ]{ 
    //lambda表达式逻辑实现 }; //2. [ ]( ) { 
    //lambda表达式逻辑实现 }; //3. [ ]()-> void { 
    //lambda表达式逻辑实现 }; 

对于有参数,有返回值的 lambda表达式写法

//一个返回值int ,参数列表int 和 int 的函数 int add(int x,int y){ 
    return x+y; } //lambada表达式等价这个函数模样 [ ](int x,int y)->int{ 
    return x+y; }; 

总结:
1.lambda的[ ]{
} 都不可以省略;
2. lambda的调用方式和普通函数以用,可以通过函数指针()去调用;
3. lambda没有返回值可以省略-> ,没有参数列表可以省略( );


lambda中的捕获列表[ ]的常用方式

对于lambda表达式[ ] 中括号里面的东西,可以添加捕获列表的值:
捕获列表表示:捕获lambda表达式外部作用域的变量
而这个外部作用域如何理解呢?lambda{ } 花括号外一层的作用域咯;


捕获列表可以有好几种形式:
1. [ ]:表示不捕获任何外部作用域的变量(当然这是非静态变量);

int main { 
    int a = 10; auto p = [] //[ ] 里面没有任何捕获变量,表示不捕获外部的任何变量 { 
    //试图获取a的值,但是是不合法的,因为[ ]没有捕获任何变量 cout<<a<<end; //非法 } return 0; } 

假如变量在静态区的变量,如全局变量,和静态变量都是直接可以在lambda表达式中使用,不需要在[ ] 里面捕获静态区的变量


2. [ &]:表示捕获外部作用域所有的变量,并且以引用的形式捕获

int main { 
    int a = 10; int b = 20; auto p = [&] //[ &] 里面有&符号,表示捕获外部的任何变量,以引用的方式捕获 { 
    //试图获取a的值, cout<<"a = "<<a<<endl;//合法 cout<<"b = "<< b<<end; //合法 //通过引用捕获的变量,可以在lambda表达式中修改 a++; //合法 b+=10; //合法 } cout<<"在lambda表达式修改了a = "<<a<<endl; //结果为11; cout<<"在lambda表达式修改了b = "<<b<<endl; //结果为30; return 0; } 

3.[ = ]:表示捕获外部作用域的所有变量,但是以值得方式捕获,并且该变量不可以在lambda表达式里面修改,修改就会报错,只有只读得功能;

int main { 
    int a = 10; int b = 20; auto p = [=] //[ =] 里面有&符号,表示捕获外部的任何变量,以值的方式捕获 { 
    //试图获取a的值, cout<<"a = "<<a<<endl;//合法 cout<<"b = "<< b<<end; //合法 // 通过值方式捕获的变量,不可以在lambda表达式中修改 a++; //非法合法 b+=10; //非法合法 } cout<<"在lambda表达式修改了a = "<<a<<endl; //结果依旧是10 cout<<"在lambda表达式修改了b = "<<b<<endl; //结果依旧是20; return 0; } 

4.[this]:捕获this指针,一般用于类里面,为的是:可以使lambda表达式里可以使用类的成员函数和成员变量;

class A { 
    private: int _i; public: void print(int x,int y) { 
    auto p = [this]{ 
    //注意:lambda表达式中无法使用形参x,y因为该lambda表达式并没有捕获该形参变量x和y cout<<x<<y<<endl; //非法  return _i; //由于有this被捕获,所以可以使用类的成员变量 }; cout<<p()<<endl; } }; 

注意:当我们类中的lambda的捕获列表是 & = 时候,是默认添加this捕获的,因为& = 的含义就是捕获外部作用域所有变量,而这里的外部作用域指的就是lambda表达式 { }`外的类里面的作用域;


5.[变量名1,变量名2,...]:单独写变量名的表示单独捕获外部作用域的变量,以值的方式捕获,并且变量在lambda表达式中无法修改值;
[&变量名1,&变量名2,...]::以引用方式单独捕获外部变量,并且该值可以在lambda表达式中修改;

class A { 
    private: int _i; public: void print(int x,int y) { 
    auto p = [this,x,&y]{ 
    //lambda表达式中使用形参x,y因为该lambda表达式捕获该形参变量x和y cout<<x<<y<<endl; //合法  y++; //合法,以引用方式捕获 cout<<y<<endl; return _i; //由于有this被捕获,所以可以使用类的成员变量 }; cout<<p()<<endl; } }; 

6.[=,&变量名1,&变量名2,...]:默认以值的方式捕获外部所有变量,而单独以引用方式捕获单独的变量;
[=,&变量名1,&变量名2,...]:默认以引用方式捕获外部所有变量,而单独以值的方式捕获单独的变量;


lambda表达式中mutable关键字

mutable:关键字表示可修改的,在lambda表达式中使用,表示可以修改以值捕获的变量

int main() { 
    int a =10; auto p = [a]()mutable{ 
    a++; //由于有mutable关键字,所以这里的a由不可以修改,变成可以修改 } cout<<a<<endl; //结果为10 return 0; } 

注意使用mutable关键之,即使lambda表达式没有参数,也需要加上( ),不可以省略;


lambda作为形参传参的用法

对于lambda表达式来说,最常用的就是作为形参传递了,类似于函数指针传参一样,本身lambda表达式就是一个匿名的函数对象,所以说,函数名可以做的,lambda表达式都可以做,但是具体用法就不演示了,只要你觉得你书写一个函数,需要函数指针传参,那么就可以考虑lambda表达式的使用,lambda表达式是一种编程习惯,看你用不用而已;
当然lambda表达式的优点也很明显:可维护性强,可以书写简明代码,阅读性好;

THE END

发表回复