目錄
一、lambda表達式的簡介
二、lambda表達式的基本語法
三、lambda表達式的使用方法
四、lambda表達式的底層原理
lambda表達式就類似于仿函數(shù),相比仿函數(shù)要更加的簡潔,我們看一下下面的代碼:
//商品類
struct Goods
{
string _name; ?// 名字
double _price; // 價格
int _evaluate; // 評價
};
在給定的商品類中,如果我們想要通過名字、價格和評價來給商品進行升序或降序。在沒有l(wèi)ambda表達式的時候,通過仿函數(shù)就可以實現(xiàn),代碼如下:
//按價格的升序
struct ComparePriceLess
{
bool operator()(const Goods& g1, const Goods& g2)
{
return g1._price< g2._price;
}
};
//按價格降序
struct ComparePriceGreater
{
bool operator()(const Goods& g1, const Goods& g2)
{
return g1._price >g2._price;
}
};
int main()
{
vectorv = { { "蘋果", 2.1, 300 }, { "香蕉", 3.3, 100 }, { "橙子", 2.2, 1000 }, { "菠蘿", 1.5, 1 } };
sort(v.begin(), v.end(), ComparePriceLess()); //按價格升序排序
sort(v.begin(), v.end(), ComparePriceGreater()); //按價格降序排序
return 0;
}
顯然這樣寫是沒有什么問題,但是,如果你寫的仿函數(shù)在取名的時候不是很貼切,導(dǎo)致他人看你寫的仿函數(shù)的時候,有可能看不懂,我們來看看lambda表達式寫出來是什么樣子的;
int main()
{
vectorv = { { "蘋果", 2.1, 300 }, { "香蕉", 3.3, 100 }, { "橙子", 2.2, 1000 }, { "菠蘿", 1.5, 1 } };
sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2)
{
return g1._price< g2._price;
}); //按價格升序排序
sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2)
{
return g1._price >g2._price;
}); //按價格降序排序
return 0;
}
二、lambda表達式的基本語法這樣一來,每次調(diào)用sort函數(shù)時只需要傳入一個lambda表達式指明比較方式即可,閱讀代碼的人一看到lambda表達式就知道本次排序的比較方式是怎樣的,提高了代碼的可讀性。?
lambda表達式書寫格式:[capture-list] (parameters) mutable ->return-type { statement }
- [capture-list] : 捕捉列表,該列表總是出現(xiàn)在lambda函數(shù)的開始位置,編譯器根據(jù)[]來判斷接下來的代碼是否為lambda函數(shù),捕捉列表能夠捕捉上下文中的變量供lambda函數(shù)使用。
- (parameters):參數(shù)列表。與普通函數(shù)的參數(shù)列表一致,如果不需要參數(shù)傳遞,則可以 連同()一起省略
- mutable:默認情況下,lambda函數(shù)總是一個const函數(shù),mutable可以取消其常量性。使用該修飾符時,參數(shù)列表不可省略(即使參數(shù)為空)。
- ->returntype:返回值類型。用追蹤返回類型形式聲明函數(shù)的返回值類型,沒有返回值時此部分可省略。返回值類型明確情況下,也可省略,由編譯器對返回類型進行推導(dǎo)。
- {statement}:函數(shù)體。在該函數(shù)體內(nèi),除了可以使用其參數(shù)外,還可以使用所有捕獲 到的變量。
lambda函數(shù)的參數(shù)列表和返回值類型都是可選部分,但捕捉列表和函數(shù)體是不可省略的,因此最簡單的lambda函數(shù)如下:?
int main()
{
//最簡單的lambda表達式,該lambda表達式?jīng)]有任何意義
[]{};
return 0;
}
三、lambda表達式的使用方法捕獲列表說明:
注意:
- [?var?]:表示值傳遞方式捕捉變量var
- [?=?]:表示值傳遞方式捕獲所有父作用域中的變量(成員函數(shù)中包括this)
- [?&var?]:表示引用傳遞捕捉變量var
- [?&?]:表示引用傳遞捕捉所有父作用域中的變量(成員函數(shù)中包括this)
- 父作用域指的是包含lambda函數(shù)的語句塊
- 語法上捕捉列表可由多個捕捉項組成,并以逗號分割。比如:[=, &a, &b],以引用傳遞的方式捕捉變量a和b,值傳遞方式捕捉其他所有變量 ;[&,a, this]:值傳遞方式捕捉變量a和this,引用方式捕捉其他變量;
- 捕捉列表不允許變量重復(fù)傳遞,否則就會導(dǎo)致編譯錯誤。 比如:[=, a]:=已經(jīng)以值傳遞方式捕捉了所有變量,捕捉a重復(fù)
- 在塊作用域以外的lambda函數(shù)捕捉列表必須為空。
- 在塊作用域中的lambda函數(shù)僅能捕捉父作用域中局部變量,捕捉任何非此作用域或者非局部變量都會導(dǎo)致編譯報錯。
- lambda表達式之間不能相互賦值,即使看起來類型相同。
使用lambda表達式進行兩數(shù)的交換
int main()
{
int a = 10, b = 20;
//這里的“->void”也是可以省略的
auto Swap = [](int& x, int& y)->void{
int tmp = x;
x = y;
y = tmp;
};
Swap(a, b);
return 0;
}
使用傳值捕捉所有
int main()
{
int a = 10, b = 20;
//傳值捕捉所有
auto Swap = [=]()mutable {
int tmp = a;
a = b;
b = tmp;
};
Swap();
//傳值捕捉a和b
auto Swap2 = [a, b]()mutable {
int tmp = a;
a = b;
b = tmp;
};
Swap2();
return 0;
}
這里需要注意,在以傳值捕捉的時候,因為lambda表達式總是一個const函數(shù),mutable可以取消其常量性,此時的圓括號也不可以省略
以引用捕捉?
int main()
{
int a = 10, b = 20;
//以引用捕捉所有
auto Swap = [&]{
int tmp = a;
a = b;
b = tmp;
};
Swap();
//以引用捕捉a和b
auto Swap2 = [&a, &b]{
int tmp = a;
a = b;
b = tmp;
};
Swap2();
//以引用捕捉a、以傳值捕捉b
auto Swap3 = [&a, b]()mutable {
int tmp = a;
a = b;
b = tmp;
};
Swap3();
return 0;
}
lambda表達式之間不能相互賦值,即使看起來類型相同
void (*PF)();
int main()
{
auto f1 = [] {cout<< "hello world"<< endl; };
auto f2 = [] {cout<< "hello world"<< endl; };
//f1 = f2; ? // 編譯失敗--->提示找不到operator=()
// 但允許使用一個lambda表達式拷貝構(gòu)造一個新的副本
auto f3(f2);
f3();
// 可以將lambda表達式賦值給相同類型的函數(shù)指針
PF = f2;
PF();
return 0;
}
四、lambda表達式的底層原理函數(shù)對象,又稱為仿函數(shù),即可以想函數(shù)一樣使用的對象,就是在類中重載了operator()運算符的類對象。
class Rate
{
public:
Rate(double rate) : _rate(rate)
{}
double operator()(double money, int year)
{
return money * _rate * year;
}
private:
double _rate;
};
int main()
{
// 函數(shù)對象
double rate = 0.49;
Rate r1(rate);
r1(10000, 2);
// lamber
auto r2 = [=](double monty, int year)->double {return monty * rate * year;};
r2(10000, 2);
return 0;
}
函數(shù)對象將rate作為其成員變量,在定義對象時給出初始值即可,lambda表達式通過捕獲列表可以直接將該變量捕獲到。
lambda表達式底層的處理方式和仿函數(shù)是一樣的,在VS下,lambda表達式在底層會被處理為函數(shù)對象,該函數(shù)對象對應(yīng)的類名叫做
。就算是兩個相同的lambda表達式,它們的uuid也是不同的;
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧
當前標題:【C++11】——lambda表達式-創(chuàng)新互聯(lián)
網(wǎng)頁地址:http://vcdvsql.cn/article10/cdgogo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站制作、網(wǎng)頁設(shè)計公司、ChatGPT、虛擬主機、電子商務(wù)、標簽優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容