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()
{
//[函數對象參數]、(操作符重載函數參數)、mutable或exception聲明、->返回值類型、{函數體 }
??????autofun1 = [](){cout <<"hellochina"<<endl; };
???fun1();
?
???autofun2 = [](inta,intb){returna +b; };
???cout <<fun2(10, 9) <<endl;
?
???std::cin.get();
}
運行結果:
案例2:
#include<functional>
#include<iostream>
#include<vector>
#include<algorithm>
?
usingnamespacestd;
?
voidmain()
{
???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);
?
???cout <<"----------------" <<endl;
?
???//直接寫在內部,下面的v表示傳遞進lambda表達式的參數
???for_each(myv.begin(),myv.end(),[](intv)
???{
??????cout <<v <<endl;
???});
?
???std::cin.get();
}
運行結果:
案例3:
#include<functional>
#include<iostream>
#include<vector>
#include<algorithm>
?
usingnamespacestd;
?
voidmain()
{
???vector<int>?myv;
???myv.push_back(1);
???myv.push_back(2);
???myv.push_back(11);
?
???inta = 10;
???// =知道a的存在,可以引用,只能讀,不可以寫,引用當前塊語句內部的局部變量
???autofun1 = [=](intv){v +=a;?cout <<v <<endl;?};
?
???for_each(myv.begin(),myv.end(),fun1);
???//此時a沒有被修改
???cout <<a <<endl;
???std::cin.get();
}
運行結果:
案例4:
#include<functional>
#include<iostream>
#include<vector>
#include<algorithm>
?
usingnamespacestd;
?
voidmain()
{
???vector<int>?myv;
???myv.push_back(1);
???myv.push_back(2);
???myv.push_back(11);
?
???inta = 10;
???//引用變量a,相當于直接操作a
???autofun1 = [&a](intv){a = 3; v +=a;?cout <<v <<endl;?};
?
???for_each(myv.begin(),myv.end(),fun1);
???//此時a發生變化
???cout <<a <<endl;
???std::cin.get();
}
運行結果:
案例5:
#include<functional>
#include<iostream>
#include<vector>
#include<algorithm>
?
usingnamespacestd;
?
voidmain()
{
???[](){cout <<"hellochina"; };//是一個函數指針
???[](){cout <<"hellochina";}();//如果沒有定義名稱,如果想調用lambda表達式,可以直接在lambda表達式的最后面加上()
?
???cin.get();
}
運行結果:
案例6:
#include<functional>
#include<iostream>
#include<vector>
#include<algorithm>
?
usingnamespacestd;
?
classtest
{
public:
???vector<int>?myv;
???intnum;
public:
???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);
???}
};
?
voidmain()
{
???testt;
???t.add();
?
???cin.get();
}
運行結果:
案:7:
#include<functional>
#include<iostream>
#include<vector>
#include<algorithm>
?
usingnamespacestd;
//返回值案例
voidmain()
{
???//double是返回值類型
???autofun1 = []()->double{cout << "hello china" <<endl;return 1; };
???fun1();
?
???//通過decltype(a/b)的方式獲得類型
???autofun2 = [](inta,doubleb)->decltype(a / b){cout << "hello china" <<endl;returna /b; };
???fun2(1, 2.3);
?
???std::cin.get();
}
運行結果:
案例8:
#include<functional>
#include<iostream>
#include<vector>
#include<algorithm>
?
usingnamespacestd;
?
void?main()
{
???inta = 10;
???//mutable使可以改副本了。如果下面的去掉將會報錯
???autofun1 = [a](intv)mutable->double{v += a;?cout <<v <<endl;a = 3;return 3; };
???cout <<a <<endl;
?
???std::cin.get();
???//運行結果還是10
}
Lambada表達式補充
| { ??????? auto func = []{return 1; }; ??????? int i = func(); ??????? CCLog("i = %d", i); ??? } ??? //最簡單的lambada表達式是只要一個中括號和一個大括號 ??? //[]捕獲列表 ??? //{}函數體 ??? //1.捕獲列表,可以放變量名,這里可以用來傳遞函數體內定義的變量 ??? { ??????? int v = 100; ??????? auto func = [v]{return v; }; ??????? int x = func(); ??? } ? ??? //2.捕獲列表,可以捕獲多個變量 ??? { ??????? int p = 100, q = 200; ??????? auto func = [p, q]{return p + q; }; ??????? int s = func(); ??? } ? ??? // 3.捕獲列表,有引用和傳值兩種方式,傳值不可以改變,引用可以改變,并且改變外部的變量值 ??? { ??????? int p = 100, q = 200; ??????? auto func = [p, &q]{q++;? return p + q; }; ??????? int s = func(); ??? } ? ??? //4.捕獲列表,可以定義mutable類型的lambada,能改變傳值的捕獲參數, ??? //但是不能改變外部的變量值 ??? { ??????? int p = 100, q = 200; ??????? auto func = [p, q]()mutable{p++; q++; return p + q; }; ??????? int s = func(); ??????? CCLog("p = %d,q = %d,s = %d", p, q, s); ??? } ? ??? //5.捕獲列表,可以用=或者&捕獲所有變量,=指傳值,&表示引用 ??? { ??????? int p = 100, q = 200; ??????? //用&的時候,所有的都可以調用了,[&,p]:表示除了p不能被使用,其它的都可以被使用 ??????? auto func = [&]{ ??????????? return p + q; ??????? }; ??? } ? ??? //稍微復雜點的lambda表達式 ??? { ??????? auto add = [](int v1, int v2){return v1 + v2; }; ??????? auto a = add(1 , 2); ??? } ? ??? //小括號中的是參數列表,參數列表和捕獲列表區別在于,參數列表的參數由調用方決定, ??? //捕獲列表由定義方決定,所以更加靈活 ? ??? //更加復雜的lambada表達是,有返回值,返回值一般都省略 ??? { ??????? //->int表示返回值是int類型的 ??????? auto add = [](int v1, int v2)->int{return v1 + v2; }; ??? } ? ??? //總結:auto func = [](){} ??? { ??????? auto func = [](){}; ??? } |
?
?
總結
以上是生活随笔為你收集整理的lambada表达式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 征信报告去哪里打
- 下一篇: 白酒股票属于什么板块