欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++11中的lambda表達(dá)式與包裝器

 更新時(shí)間:2025年07月18日 10:01:03   作者:古月-一個(gè)C++方向的小白  
C++11中l(wèi)ambda是匿名函數(shù),可捕獲外部變量,std::function統(tǒng)一存儲(chǔ)可調(diào)用對(duì)象,bind調(diào)整參數(shù)順序和數(shù)量,兩者簡化了函數(shù)對(duì)象的使用,本文給大家介紹C++11中的lambda表達(dá)式與包裝器,感興趣的朋友一起看看吧

lambda語法

lambda 表達(dá)式本質(zhì)是?個(gè)匿名函數(shù)對(duì)象,跟普通函數(shù)不同的是他可以定義在函數(shù)內(nèi)部。
lambda 表達(dá)式語法使?層??沒有類型,所以我們?般是?auto或者模板參數(shù)定義的對(duì)象去接收 lambda 對(duì)象
lambda表達(dá)式的格式: [capture-list] (parameters)-> return type {function boby }

  1. [capture-list] : 捕捉列表,該列表總是出現(xiàn)在 lambda 函數(shù)的開始位置,編譯器根據(jù)[]來判斷接下來的代碼是否為 lambda 函數(shù),捕捉列表能夠捕捉上?中的變量供 lambda 函數(shù)使用,捕捉列表可以傳值和傳引?捕捉。捕捉列表為空也不能省略。(捕捉列表只能是已經(jīng)定義的)
  2. (parameters) :參數(shù)列表,與普通函數(shù)的參數(shù)列表功能類似,如果不需要參數(shù)傳遞,則可以連同()?起省略
  3. ->return type :返回值類型,?追蹤返回類型形式聲明函數(shù)的返回值類型,沒有返回值時(shí)此部分可省略。?般返回值類型明確情況下,也可省略,由編譯器對(duì)返回類型進(jìn)?推導(dǎo)。
  4. {function boby} :函數(shù)體,函數(shù)體內(nèi)的實(shí)現(xiàn)跟普通函數(shù)完全類似,在該函數(shù)體內(nèi),除了可以使?其參數(shù)外,還可以使?所有捕獲到的變量,函數(shù)體為空也不能省略。
auto add1 = [](int x, int y)->int {return x + y; };
cout << add1(1, 2) << endl;
// 1、捕捉為空也不能省略
// 2、參數(shù)為空可以省略
// 3、返回值可以省略,可以通過返回對(duì)象?動(dòng)推導(dǎo)
// 4、函數(shù)題不能省略
auto func1 = []
{
	cout << "hello bit" << endl;
	return 0;
};

捕捉列表

  1. lambda 表達(dá)式中默認(rèn)只能? lambda 函數(shù)體和參數(shù)中的變量,如果想用外層作?域中的變量就需要進(jìn)?捕捉
  2. 第?種捕捉?式是在捕捉列表中顯?的傳值捕捉和傳引?捕捉,捕捉的多個(gè)變量?逗號(hào)分割。[x,y, &z] 表?x和y值捕捉,z引?捕捉。
  3. 第?種捕捉?式是在捕捉列表中隱式捕捉,我們?cè)诓蹲搅斜韺?個(gè)=表?隱式值捕捉,在捕捉列表寫?個(gè)&表?隱式引?捕捉,這樣我們 lambda 表達(dá)式中?了那些變量,編譯器就會(huì)?動(dòng)捕捉那些變量
  4. 第三種捕捉?式是在捕捉列表中混合使?隱式捕捉和顯?捕捉。[=, &x]表?其他變量隱式值捕捉,x引?捕捉;[&, x, y]表?其他變量引?捕捉,x和y值捕捉。當(dāng)使用混合捕捉時(shí),第?個(gè)元素必須是&或=,并且&混合捕捉時(shí),后?的捕捉變量必須是值捕捉,同理=混合捕捉時(shí),后面的捕捉變量必須是引用捕捉。
  5. lambda 表達(dá)式如果在函數(shù)局部域中,他可以捕捉 lambda 位置之前定義的變量,不能捕捉靜態(tài)局部變量和全局變量,靜態(tài)局部變量和全局變量也不需要捕捉, lambda 表達(dá)式中可以直接使?。這也意味著 lambda 表達(dá)式如果定義在全局位置,捕捉列表必須為空。(但是一般都是將lambda定義在局部區(qū)域
  6. 默認(rèn)情況下, lambda 捕捉列表是被const修飾的,也就是說傳值捕捉的過來的對(duì)象不能修改,mutable加在參數(shù)列表的后?可以取消其常量性,也就說使?該修飾符后,傳值捕捉的對(duì)象就可以修改了,但是修改還是形參對(duì)象,不會(huì)影響實(shí)參。使?該修飾符后,參數(shù)列表不可省略(即使參數(shù)為空)。
auto func1 = [a, &b]
{
	// 值捕捉的變量不能修改,引?捕捉的變量可以修改
	//a++;
	b++;
	int ret = a + b;
	return ret;
};
auto func2 = [=]
{
	int ret = a + b + c;
	return ret;
};
auto func6 = []
{
	int ret = x + m;
	return ret;
};
auto func4 = [&, a, b]
{
	//a++;
	//b++;
	c++;
	d++;
	return a + b + c + d;
};
auto func5 = [=, &a, &b]
{
	a++;
	b++;
	/*c++;
	d++;*/
	return a + b + c + d;
};
auto func7 = [=]()mutable
{
	a++;
	b++;
	c++;
};

但如果lambda是寫在類里面的,那么lambda是不能夠捕獲私有成員變量的,也是不能直接使用的,如果想使用需要捕獲this指針

class A
{
public:
	void f()
	{
		auto add1 = [this](int a,int b){return a + b + _a1 + _a2};
	}
private:
int _a1 = 1;
int _a2 = 2;
};

lambda的應(yīng)用

在學(xué)習(xí) lambda 表達(dá)式之前,可調(diào)用對(duì)象只有函數(shù)指針和仿函數(shù)對(duì)象,函數(shù)指針的類型定義起來比較麻煩,仿函數(shù)要定義?個(gè)類,相對(duì)會(huì)比較麻煩。使用 lambda 去定義可調(diào)用對(duì)象,既簡單又方便。

sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {
return g1._price < g2._price;
});

因?yàn)?code>sort會(huì)將迭代器區(qū)間傳給后面的對(duì)象,所以需要兩個(gè)參數(shù)。

lambda的原理

  1. lambda 的原理和范圍for很像,編譯后從匯編指令層的角度看,壓根就沒有l(wèi)ambda 和范圍for這樣的東西。范圍for底層是迭代器,?lambda底層是仿函數(shù)對(duì)象,也就說我們寫了?個(gè)lambda 以后,編譯器會(huì)?成?個(gè)對(duì)應(yīng)的仿函數(shù)的類。
  2. 仿函數(shù)的類名是編譯按?定規(guī)則?成的,保證不同的 lambda ?成的類名不同,lambda參數(shù)/返回類型/函數(shù)體就是仿函數(shù)operator()的參數(shù)/返回類型/函數(shù)體, lambda 的捕捉列表本質(zhì)是?成的仿函數(shù)類的成員變量,也就是說捕捉列表的變量都是 lambda 類構(gòu)造函數(shù)的實(shí)參,當(dāng)然隱式捕捉,編譯器要看使?哪些就傳那些對(duì)象。

包裝器

function

std::function 是?個(gè)類模板,也是?個(gè)包裝器。 std::function 的實(shí)例對(duì)象可以包裝存儲(chǔ)其他的可以調(diào)?對(duì)象,包括函數(shù)指針、仿函數(shù)、 lambda 、 bind 表達(dá)式等,存儲(chǔ)的可調(diào)用對(duì)象被稱為 std::function 的?標(biāo)。若 std::function 不含?標(biāo),則稱它為空。調(diào)?空std::function 的?標(biāo)導(dǎo)致拋出 std::bad_function_call 異常

int f(int a, int b)
{
	return a + b;
}
struct Fun
{
public:
	int operator()(int a,int b)
	{
		return (a + b) * 10;
	}
};
int main()
{
	auto lf = [](int a, int b) {return (a + b) * 30; };
	function<int(int, int)>f1(f);
	//function<int(int, int)>f2(Fun());編譯器會(huì)將其解釋為函數(shù)聲明而不是變量定義,這被稱為"最令人煩惱的解析"
	function<int(int, int)>f2 = Fun();
	function<int(int, int)>f3(lf);
	vector<function<int(int, int)>>Vf = { f,Fun(),lf };
	cout << f1(2, 3) << endl;
	cout << f2(1, 2) << endl;
	cout << lf(4, 5) << endl;
	for (auto p : Vf)
	{
		cout << p(1, 2) << endl;
	}
	return 0;
}

函數(shù)指針、仿函數(shù)、 lambda 等可調(diào)?對(duì)象的類型各不相同, std::function 的優(yōu)勢就是統(tǒng)?類型,對(duì)他們都可以進(jìn)?包裝,這樣在很多地?就?便聲明可調(diào)?對(duì)象的類型。
可以把function當(dāng)做把可調(diào)用對(duì)象進(jìn)行統(tǒng)一為一個(gè)類型,這樣就可以將其儲(chǔ)存到容器中。
如果包的是成員函數(shù)的話需要注意,由于類的成員函數(shù)的第一個(gè)參數(shù)是默認(rèn)為this指針,所以function實(shí)例化的類型需要有類的對(duì)象的地址或者是對(duì)象,即使傳的是對(duì)象,對(duì)象會(huì)使用.*操作符對(duì)this指針進(jìn)行調(diào)用。

class Plus
{
	public:
	Plus(int n = 10)
	:_n(n)
	{}
	static int plusi(int a, int b)
	{
	return a + b;
	}
	double plusd(double a, double b)
	{
	return (a + b) * _n;
	}
	private:
	int _n;
};
int main()
{
	// 包裝靜態(tài)成員函數(shù)
	// 成員函數(shù)要指定類域并且前?加&才能獲取地址
	//靜態(tài)成員函數(shù)是可以不加&
	function<int(int, int)> f4 = &Plus::plusi;
	cout << f4(1, 1) << endl;
	// 包裝普通成員函數(shù)
	// 普通成員函數(shù)還有?個(gè)隱含的this指針參數(shù),所以綁定時(shí)傳對(duì)象或者對(duì)象的指針過去都可以
	function<double(Plus*, double, double)> f5 = &Plus::plusd;
	Plus pd;
	cout << f5(&pd, 1.1, 1.1) << endl;
	function<double(Plus, double, double)> f6 = &Plus::plusd;
	cout << f6(pd, 1.1, 1.1) << endl;
	cout << f6(pd, 1.1, 1.1) << endl;
	function<double(Plus&&, double, double)> f7 = &Plus::plusd;
	cout << f7(move(pd), 1.1, 1.1) << endl;
	cout << f7(Plus(), 1.1, 1.1) << endl;
}

bind

  1. bind 是?個(gè)函數(shù)模板,它也是?個(gè)可調(diào)?對(duì)象的包裝器,可以把他看做?個(gè)函數(shù)適配器,對(duì)接收的fn可調(diào)?對(duì)象進(jìn)?處理后返回?個(gè)可調(diào)?對(duì)象。 bind 可以?來調(diào)整參數(shù)個(gè)數(shù)和參數(shù)順序。bind 也在<functional>這個(gè)頭?件中。
  2. 調(diào)?bind的?般形式: auto newCallable = bind(callable,arg_list); 其中newCallable本?是?個(gè)可調(diào)?對(duì)象,arg_list是?個(gè)逗號(hào)分隔的參數(shù)列表,對(duì)應(yīng)給定的callable的參數(shù)。當(dāng)我們調(diào)?newCallable時(shí),newCallable會(huì)調(diào)用callable,并傳給它arg_list中的參數(shù)。
  3. arg_list中的參數(shù)可能包含形如_n的名字,其中n是?個(gè)整數(shù),這些參數(shù)是占位符,表?newCallable的參數(shù),它們占據(jù)了傳遞給newCallable的參數(shù)的位置。數(shù)值n表??成的可調(diào)?對(duì)象中參數(shù)的位置:_1為newCallable的第?個(gè)參數(shù),_2為第?個(gè)參數(shù),以此類推。_1/_2/_3…這些占位符放到placeholders的?個(gè)命名空間中。
using placeholders::_1;
using placeholders::_2;
using placeholders::_3;
int Sub(int a, int b)
{
	return (a - b) * 10;
}
int main()
{
	auto sub1 = bind(Sub, _1, _2);
	cout << sub1(10, 5) << endl;
	// bind 本質(zhì)返回的?個(gè)仿函數(shù)對(duì)象
	// 調(diào)整參數(shù)順序(不常?)
	// _1代表第?個(gè)實(shí)參
	// _2代表第?個(gè)實(shí)參
	// ...
	auto sub2 = bind(Sub, _2, _1);
	cout << sub2(10, 5) << endl;
	// 調(diào)整參數(shù)個(gè)數(shù) (常?)
	auto sub3 = bind(Sub, 100, _1);
	cout << sub3(5) << endl;
	auto sub4 = bind(Sub, _1, 100);
	cout << sub4(5) << endl;
	// 分別綁死第123個(gè)參數(shù)
	auto sub5 = bind(SubX, 100, _1, _2);
	cout << sub5(5, 1) << endl;
	cout << bind(SubX, 100, _1, _2)(5, 1) << endl;
	auto sub6 = bind(SubX, _1, 100, _2);
	cout << sub6(5, 1) << endl;
	auto sub7 = bind(SubX, _1, _2, 100);
	cout << sub7(5, 1) << endl;
	return 0;
}

bind對(duì)于我們之前用function來包裝成員函數(shù)時(shí)第一個(gè)參數(shù)必須傳對(duì)象的情況做出了改變,可以用bind來綁定第一個(gè)參數(shù),這樣在后續(xù)調(diào)用該可調(diào)用對(duì)象的時(shí)候就可以不用傳對(duì)象了

// 成員函數(shù)對(duì)象進(jìn)?綁死,就不需要每次都傳遞了
function<double(Plus&&, double, double)> f6 = &Plus::plusd;
Plus pd;
cout << pd.plusd(1.1, 1.1) << endl;
cout << f6(move(pd), 1.1, 1.1) << endl;
cout << f6(Plus(), 1.1, 1.1) << endl;
auto f = bind(&Plus::plusd, &pd, _1, _2);
function<double(double, double)> f2 = bind(&Plus::plusd, &pd, _1, _2);
cout << f(1.1,1.1) << endl;
cout << f2(1.1, 1.1) << endl;

到此這篇關(guān)于C++11之lambda表達(dá)式與包裝器的文章就介紹到這了,更多相關(guān)C++ lambda表達(dá)式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語言float內(nèi)存布局示例詳解

    C語言float內(nèi)存布局示例詳解

    這篇文章主要為大家介紹了C語言float內(nèi)存布局示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • 詳解C++中的萬能頭文件

    詳解C++中的萬能頭文件

    C++萬能頭文件它是一個(gè)包含了每一個(gè)標(biāo)準(zhǔn)庫的頭文件,接下來通過本文給大家介紹C++中的萬能頭文件及優(yōu)缺點(diǎn),需要的朋友可以參考下
    2023-02-02
  • C語言動(dòng)態(tài)內(nèi)存管理介紹

    C語言動(dòng)態(tài)內(nèi)存管理介紹

    大家好,本篇文章主要講的是C語言動(dòng)態(tài)內(nèi)存管理介紹,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • 使用C語言實(shí)現(xiàn)內(nèi)存池的示例代碼

    使用C語言實(shí)現(xiàn)內(nèi)存池的示例代碼

    所謂內(nèi)存池,顧名思義和線程池的設(shè)計(jì)原理是一樣的,為了減少頻繁申請(qǐng)釋放內(nèi)存而帶來的資源消耗,減少釋放內(nèi)存后產(chǎn)生的內(nèi)存碎片,下面我們就來看看如何使用C語言實(shí)現(xiàn)內(nèi)存池吧
    2024-02-02
  • C語言版醫(yī)院管理系統(tǒng)

    C語言版醫(yī)院管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C語言版醫(yī)院管理系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • 如何寫好C main函數(shù)的幾個(gè)注意事項(xiàng)

    如何寫好C main函數(shù)的幾個(gè)注意事項(xiàng)

    這篇文章主要介紹了如何寫好C main函數(shù)的幾個(gè)注意事項(xiàng),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • C語言 文件的打開與關(guān)閉詳解及示例代碼

    C語言 文件的打開與關(guān)閉詳解及示例代碼

    本文主要介紹C語言 文件的基礎(chǔ)知識(shí),這里整理了相關(guān)資料及示例代碼,有興趣的小伙伴可以參考下
    2016-08-08
  • C++ OpenCV實(shí)戰(zhàn)之網(wǎng)孔檢測的實(shí)現(xiàn)

    C++ OpenCV實(shí)戰(zhàn)之網(wǎng)孔檢測的實(shí)現(xiàn)

    這篇文章主要介紹了如何利用C++和OpenCV實(shí)現(xiàn)網(wǎng)孔檢測,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)OpenCV有一定幫助,感興趣的小伙伴可以了解一下
    2022-05-05
  • C語言中的數(shù)組指針數(shù)組與函數(shù)指針數(shù)組

    C語言中的數(shù)組指針數(shù)組與函數(shù)指針數(shù)組

    數(shù)組指針數(shù)組和函數(shù)指針數(shù)組是兩個(gè)強(qiáng)大但容易混淆的概念,下面就來介紹一下C語言中的數(shù)組指針數(shù)組與函數(shù)指針數(shù)組的區(qū)別,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-06-06
  • C++中l(wèi)ist的用法實(shí)例講解

    C++中l(wèi)ist的用法實(shí)例講解

    list是順序容器的一種,list是一個(gè)雙向鏈表,使用list需要包含頭文件list,這篇文章主要給大家介紹了關(guān)于C++中l(wèi)ist的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2021-11-11

最新評(píng)論