天天看點

lambada表達式



lambda表達式

//c++ 11中的lambda表達式用于定義并建立匿名的函數對象,以簡化程式設計工作。lambda的文法形式如下:

//[函數對象參數](操作符重載函數參數)mutable或exception聲明->傳回值類型{函數體

}

//可以看到,lambda主要分為五個部分:

//[函數對象參數]、(操作符重載函數參數)、mutable或exception聲明、->傳回值類型、{函數體

}。下面分别進行介紹。

//一、[函數對象參數],辨別一個lambda的開始,這部分必須存在,不能省略。函數對象參數是傳遞給編譯器自動生成的函數對象類的構造函數的。

//函數對象參數隻能使用那些到定義lambda為止時lambda所在作用範圍内可見的局部變量(包括lambda所在類的this)。函數對象參數有以下形式:

//1、空。沒有使用任何函數對象參數。

//2、 =。函數體内可以使用lambda所在作用範圍内所有可見的局部變量(包括lambda所在類的this),并且是值傳遞方式(相當于編譯器自動為我們按值傳遞了所有局部變量)。

//3、&。函數體内可以使用lambda所在作用範圍内所有可見的局部變量(包括lambda所在類的this),并且是引用傳遞方式(相當于編譯器自動為我們按引用傳遞了所有局部變量)。

//4、this。函數體内可以使用lambda所在類中的成員變量。

//5、a。将a按值進行傳遞。按值進行傳遞時,函數體内不能修改傳遞進來的a的拷貝,因為預設情況下函數是const的。要修改傳遞進來的a的拷貝,可以添加mutable修飾符。

//6、&a。将a按引用進行傳遞。

//7、a, &b。将a按值進行傳遞,b按引用進行傳遞。

//8、 =,&a,&b。除a和b按引用進行傳遞外,其他參數都按值進行傳遞。

//9、&, a, b。除a和b按值進行傳遞外,其他參數都按引用進行傳遞。

//二、(操作符重載函數參數),辨別重載的()操作符的參數,沒有參數時,這部分可以省略。參數可以通過按值(如:(a,

b))和按引用(如:(&a, &b))兩種方式進行傳遞。

//三、mutable或exception聲明,這部分可以省略。按值傳遞函數對象參數時,加上mutable修飾符後,可以修改按值傳遞進來的拷貝(注意是能修改拷貝,而不是值本身)。

//exception聲明用于指定函數抛出的異常,如抛出整數類型的異常,可以使用throw(int)。

//四、->傳回值類型,辨別函數傳回值的類型,當傳回值為void,或者函數體中隻有一處return的地方(此時編譯器可以自動推斷出傳回值類型)時,這部分可以省略。

//五、{函數體

},辨別函數的實作,這部分不能省略,但函數體可以為空。

案例1:

#include<functional>

#include<iostream>

#include<vector>

#include<algorithm>

usingnamespacestd;

//lambda表達式簡單案例

voidmain()

{

      autofun1

= [](){cout <<"hellochina"<<endl;

};

   fun1();

   autofun2

= [](inta,intb){returna

+b; };

   cout

<<fun2(10, 9) <<endl;

   std::cin.get();

運作結果:

lambada表達式

案例2:

   vector<int> myv;

   myv.push_back(1);

   myv.push_back(2);

   myv.push_back(11);

   autofun1

= [](intv){ cout

<<v <<endl;

   //通過這種方式操作myv中的值

   for_each(myv.begin(),myv.end(),fun1);

<<"----------------" <<endl;

   //直接寫在内部,下面的v表示傳遞進lambda表達式的參數

   for_each(myv.begin(),myv.end(),[](intv)

   {

      cout

   });

lambada表達式

案例3:

   inta

= 10;

   // =知道a的存在,可以引用,隻能讀,不可以寫,引用目前塊語句内部的局部變量

= [=](intv){v

+=a; cout

<<v <<endl; };

   //此時a沒有被修改

<<a <<endl;

lambada表達式

案例4:

   //引用變量a,相當于直接操作a

= [&a](intv){a

= 3; v +=a; cout

   //此時a發生變化

lambada表達式

案例5:

   [](){cout

<<"hellochina"; };//是一個函數指針

<<"hellochina";}();//如果沒有定義名稱,如果想調用lambda表達式,可以直接在lambda表達式的最後面加上()

   cin.get();

lambada表達式

案例6:

classtest

public:

   intnum;

   voidadd()

       num

= 12;

       myv.push_back(10);

       myv.push_back(11);

       //[]引用this

       int x

= 3;

       autofun1

= [this,x](intv){cout

<<v+x+this->num

<< endl; };

       //=按照副本引用this,還有目前塊語句局部變量,不可以指派,但是可以讀取

       //&按照引用的方式操作局部變量,this,可以指派,可以讀取

       //副本引用a,[=]  [a]

       //引用a

[&] [&a]

       autofun2

= [&](intv){cout

<<v +x

+this->num

<< endl;x

= 3; };

       for_each(this->myv.begin(),this->myv.end(),fun1);

       cout

<<"-----------------" <<endl;

       for_each(this->myv.begin(),this->myv.end(),fun2);

   }

   testt;

   t.add();

lambada表達式

案:7:

//傳回值案例

   //double是傳回值類型

= []()->double{cout

<< "hello china" <<endl;return

1; };

   //通過decltype(a/b)的方式獲得類型

= [](inta,doubleb)->decltype(a

/ b){cout

<< "hello china" <<endl;returna

/b; };

   fun2(1,

2.3);

lambada表達式

案例8:

void main()

   //mutable使可以改副本了。如果下面的去掉将會報錯

= [a](intv)mutable->double{v

+= a; cout

<<v <<endl;a

= 3;return 3; };

   //運作結果還是10

lambada表達式補充

        auto

func = []{return 1; };

        int

i = func();

        cclog("i = %d",

i);

    }

    //最簡單的lambada表達式是隻要一個中括号和一個大括号

    //[]捕獲清單

    //{}函數體

    //1.捕獲清單,可以放變量名,這裡可以用來傳遞函數體内定義的變量

    {

v = 100;

func = [v]{return

v; };

x = func();

    //2.捕獲清單,可以捕獲多個變量

p = 100, q = 200;

func = [p, q]{return

p + q; };

s = func();

    // 3.捕獲清單,有引用和傳值兩種方式,傳值不可以改變,引用可以改變,并且改變外部的變量值

func = [p, &q]{q++; 

return p +

q; };

    //4.捕獲清單,可以定義mutable類型的lambada,能改變傳值的捕獲參數,

    //但是不能改變外部的變量值

func = [p, q]()mutable{p++;

q++; return

        cclog("p = %d,q = %d,s = %d",

p, q,

s);

    //5.捕獲清單,可以用=或者&捕獲所有變量,=指傳值,&表示引用

        //用&的時候,所有的都可以調用了,[&,p]:表示除了p不能被使用,其它的都可以被使用

func = [&]{

            return

p + q;

        };

    //稍微複雜點的lambda表達式

add = [](int v1,

int v2){return

v1 + v2; };

a = add(1 , 2);

    //小括号中的是參數清單,參數清單和捕獲清單差別在于,參數清單的參數由調用方決定,

    //捕獲清單由定義方決定,是以更加靈活

    //更加複雜的lambada表達是,有傳回值,傳回值一般都省略

        //->int表示傳回值是int類型的

int v2)->int{return

    //總結:auto func = [](){}

func = [](){};

繼續閱讀