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

C++11中的可變參數(shù)模板/lambda表達(dá)式

 更新時(shí)間:2023年03月24日 09:52:10   作者:二肥是只大懶藍(lán)貓  
C++11的新特性可變參數(shù)模板能夠讓我們創(chuàng)建可以接受可變參數(shù)的函數(shù)模板和類模板,相比C++98和C++03,類模板和函數(shù)模板中只能含固定數(shù)量的模板參數(shù),可變參數(shù)模板無疑是一個(gè)巨大的改進(jìn),這篇文章主要介紹了C++11中的可變參數(shù)模板/lambda表達(dá)式,需要的朋友可以參考下

1.可變參數(shù)模板

C++11的新特性可變參數(shù)模板能夠讓我們創(chuàng)建可以接受可變參數(shù)的函數(shù)模板和類模板,相比C++98和C++03,類模板和函數(shù)模板中只能含固定數(shù)量的模板參數(shù),可變參數(shù)模板無疑是一個(gè)巨大的改進(jìn)。可是可變參數(shù)模板比較抽象,因此這里只會寫出夠我們使用的部分。

 下面是一個(gè)基本可變參數(shù)的函數(shù)模板

// Args是一個(gè)模板參數(shù)包,args是一個(gè)函數(shù)形參參數(shù)包
// 聲明一個(gè)參數(shù)包Args...args,這個(gè)參數(shù)包中可以包含0到任意個(gè)模板參數(shù)。
template <class ...Args>
void ShowList(Args... args)
{}

上面的參數(shù)args前面有省略號,所以它就是一個(gè)可變模版參數(shù),我們把帶省略號的參數(shù)稱為“參數(shù)
包”,它里面包含了0到N(N>=0)個(gè)模版參數(shù)。我們無法直接獲取參數(shù)包args中的每個(gè)參數(shù)的,只能通過展開參數(shù)包的方式來獲取參數(shù)包中的每個(gè)參數(shù),這是使用可變模版參數(shù)的一個(gè)主要特點(diǎn),也是最大的難點(diǎn),即如何展開可變模版參數(shù)。

遞歸函數(shù)方式展開參數(shù)包

//遞歸終止函數(shù)
template <class T>
void showList(const T& t)
{
	cout << y << endl;
}
//展開函數(shù)
template<class T,class ...Args>
void showList(T value, Args... args)
{
	cout << value << " ";
	showList(args...);
}
int main()
{
	showList(1);
	showList(1,'A');
	showList(1,'A',std::string("sort"));
 
	return 0;
}

 代碼分析:

①showList(1): 如果只有一個(gè)參數(shù),那會直接調(diào)用第一個(gè)showList函數(shù)。

②showList(1,'A'): 匹配到第二個(gè)showList函數(shù)后,先將1打印出來。然后通過遞歸,看看args里面有多少個(gè)參數(shù),如果只有一個(gè),比如這里的'A',那么就會去調(diào)用第一個(gè)showList函數(shù)。

③showList(1,'A',"sort"): 匹配到第二個(gè)showList函數(shù)后,先將1打印出來。然后通過遞歸,看看args里面有多少個(gè)參數(shù),這里有兩個(gè),那么繼續(xù)調(diào)用第二個(gè)showList函數(shù),此時(shí)的value變成了'A',依次類推。

逗號表達(dá)式展開參數(shù)包

這種展開參數(shù)包的方式,不需要通過遞歸終止函數(shù),是直接在expand函數(shù)體中展開的, printarg不是一個(gè)遞歸終止函數(shù),只是一個(gè)處理參數(shù)包中每一個(gè)參數(shù)的函數(shù)。這種就地展開參數(shù)包的方式實(shí)現(xiàn)的關(guān)鍵是逗號表達(dá)式。我們知道逗號表達(dá)式會按順序執(zhí)行逗號前面的表達(dá)式。

expand函數(shù)中的逗號表達(dá)式:(printarg(args), 0),也是按照這個(gè)執(zhí)行順序,先執(zhí)行printarg(args),再得到逗號表達(dá)式的結(jié)果0。同時(shí)還用到了C++11的另外一個(gè)特性——初始化列表,通過初始化列表來初始化一個(gè)變長數(shù)組, {(printarg(args), 0)...}將會展開成((printarg(arg1),0),(printarg(arg2),0), (printarg(arg3),0), etc... ),最終會創(chuàng)建一個(gè)元素值都為0的數(shù)組int arr[sizeof...(Args)]。由于是逗號表達(dá)式,在創(chuàng)建數(shù)組的過程中會先執(zhí)行逗號表達(dá)式前面的部分printarg(args)打印出參數(shù),也就是說在構(gòu)造int數(shù)組的過程中就將參數(shù)包展開了,這個(gè)數(shù)組的目的純粹是為了在數(shù)組構(gòu)造的過程展開參數(shù)包。

template <class T>
void PrintArg(T t)
{
	cout << t << " ";
}
//展開函數(shù)
template <class ...Args>
void ShowList(Args... args)
{
	int arr[] = { (PrintArg(args), 0)... };
	cout << endl;
}
int main()
{
	ShowList(1);
	ShowList(1, 'A');
	ShowList(1, 'A', std::string("sort"));
	return 0;
}

STL容器中的empalce相關(guān)接口函數(shù):

template <class... Args>
void emplace_back (Args&&... args)

首先我們看到的emplace系列的接口,支持模板的可變參數(shù),并且萬能引用。那么相對insert和
emplace系列接口的優(yōu)勢到底在哪里呢

int main()
{
	std::list< std::pair<int, char> > mylist;
	// emplace_back支持可變參數(shù),拿到構(gòu)建pair對象的參數(shù)后自己去創(chuàng)建對象
	// 那么在這里我們可以看到除了用法上,和push_back沒什么太大的區(qū)別
	mylist.emplace_back(10, 'a');
	mylist.emplace_back(20, 'b');
	mylist.emplace_back(make_pair(30, 'c'));
	mylist.push_back(make_pair(40, 'd'));
	mylist.push_back({ 50, 'e' });
	for (auto e : mylist)
		cout << e.first << ":" << e.second << endl;
	return 0;
}

2.lambda表達(dá)式

在C++98中,如果想要對一個(gè)數(shù)據(jù)集合中的元素進(jìn)行排序,可以使用std::sort方法

int main()
{
	int array[] = { 4,1,8,5,3,7,0,9,2,6 };
	// 默認(rèn)按照小于比較,排出來結(jié)果是升序
	std::sort(array, array + sizeof(array) / sizeof(array[0]));
	// 如果需要降序,需要改變元素的比較規(guī)則
	std::sort(array, array + sizeof(array) / sizeof(array[0]), greater<int>());
	return 0;
}

如果待排序元素為自定義類型,還需要我們定義排序時(shí)的比較規(guī)則。隨著C++語法的發(fā)展,人們開始覺得這種寫法太復(fù)雜了,每次為了實(shí)現(xiàn)一個(gè)algorithm算法,都要重新去寫一個(gè)類,如果每次比較的邏輯不一樣,還要去實(shí)現(xiàn)多個(gè)類,特別是相同類的命名,這些都給編程者帶來了極大的不便。因此,在C++11語法中出現(xiàn)了Lambda表達(dá)式。

先來看看lambda表達(dá)式的例子:

//自定義類型
struct Goods
{
	string _name; // 名字
	double _price; // 價(jià)格
	int _evaluate; // 評價(jià)
	Goods(const char* str, double price, int evaluate)
		:_name(str)
		, _price(price)
		, _evaluate(evaluate)
	{}
};
int main()
{
	vector<Goods> v = { { "蘋果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2,
	3 }, { "菠蘿", 1.5, 4 } };
 
	//比較價(jià)格
	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; });
 
	//比較評價(jià)
	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {
		return g1._evaluate < g2._evaluate; });
 
	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {
		return g1._evaluate > g2._evaluate; });
	return 0;
}

上述代碼就是使用C++11中的lambda表達(dá)式來解決,可以看出lambda表達(dá)式實(shí)際是一個(gè)匿名函數(shù)。

lambda表達(dá)式語法

ambda表達(dá)式書寫格式:[capture-list] (parameters) mutable -> return-type { statement}

lambda表達(dá)式各部分說明:

[capture-list] : 捕捉列表,該列表總是出現(xiàn)在lambda函數(shù)的開始位置,編譯器根據(jù)[]來判斷接下來的代碼是否為lambda函數(shù),捕捉列表能夠捕捉上下文中的變量供lambda函數(shù)使用。

 (parameters):參數(shù)列表。與普通函數(shù)的參數(shù)列表一致,如果不需要參數(shù)傳遞,則可以連同()一起省略

 mutable:默認(rèn)情況下,lambda函數(shù)總是一個(gè)const函數(shù),mutable可以取消其常量性。使用該修飾符時(shí),參數(shù)列表不可省略(即使參數(shù)為空)。

->returntype:返回值類型。用追蹤返回類型形式聲明函數(shù)的返回值類型,沒有返回值時(shí)此部分可省略。返回值類型明確情況下,也可省略,由編譯器對返回類型進(jìn)行推導(dǎo)。

 {statement}:函數(shù)體。在該函數(shù)體內(nèi),除了可以使用其參數(shù)外,還可以使用所有捕獲到的變量。

注意:

在lambda函數(shù)定義中,參數(shù)列表和返回值類型都是可選部分,而捕捉列表和函數(shù)體可以為空。因此C++11中最簡單的lambda函數(shù)為:[]{}; 該lambda函數(shù)不能做任何事情。

int main()
{
	// 最簡單的lambda表達(dá)式, 該lambda表達(dá)式?jīng)]有任何意義
	[] {};
	// 省略參數(shù)列表和返回值類型,返回值類型由編譯器推導(dǎo)為int
	int a = 3, b = 4;
	[=] {return a + 3; };
	// 省略了返回值類型,無返回值類型
	auto fun1 = [&](int c) {b = a + c; };
	fun1(10)
		cout << a << " " << b << endl;
	// 各部分都很完善的lambda函數(shù)
	auto fun2 = [=, &b](int c)->int {return b += a + c; };
	cout << fun2(10) << endl;
	// 復(fù)制捕捉x
	int x = 10;
	auto add_x = [x](int a) mutable { x *= 2; return a + x; };
	cout << add_x(10) << endl;
	return 0;
}

通過上述例子可以看出,lambda表達(dá)式實(shí)際上可以理解為無名函數(shù),該函數(shù)無法直接調(diào)用,如果想要直接調(diào)用,可借助auto將其賦值給一個(gè)變量。

捕獲列表說明:

捉列表描述了上下文中那些數(shù)據(jù)可以被lambda使用,以及使用的方式傳值還是傳引用。

[var]:表示值傳遞方式捕捉變量var

 [=]:表示值傳遞方式捕獲所有父作用域中的變量(包括this)

 [&var]:表示引用傳遞捕捉變量var

 [&]:表示引用傳遞捕捉所有父作用域中的變量(包括this)

 [this]:表示值傳遞方式捕捉當(dāng)前的this指針

注意:
a. 父作用域指包含lambda函數(shù)的語句塊

b. 語法上捕捉列表可由多個(gè)捕捉項(xiàng)組成,并以逗號分割。比如:[=, &a, &b]:以引用傳遞的方式捕捉變量a和b,值傳遞方式捕捉其他所有變量[&,a, this]:值傳遞方式捕捉變量a和this,引用方式捕捉其他變量

c. 捕捉列表不允許變量重復(fù)傳遞,否則就會導(dǎo)致編譯錯(cuò)誤。比如:[=, a]:=已經(jīng)以值傳遞方式捕捉了所有變量,捕捉a重復(fù)

d. 在塊作用域以外的lambda函數(shù)捕捉列表必須為空。

e. 在塊作用域中的lambda函數(shù)僅能捕捉父作用域中局部變量,捕捉任何非此作用域或者非局部變量都會導(dǎo)致編譯報(bào)錯(cuò)。

f. lambda表達(dá)式之間不能相互賦值,即使看起來類型相同

到此這篇關(guān)于C++11中的可變參數(shù)模板/lambda表達(dá)式的文章就介紹到這了,更多相關(guān)C++11 lambda表達(dá)式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語言超詳細(xì)講解隊(duì)列的實(shí)現(xiàn)及代碼

    C語言超詳細(xì)講解隊(duì)列的實(shí)現(xiàn)及代碼

    隊(duì)列(Queue)與棧一樣,是一種線性存儲結(jié)構(gòu),它具有如下特點(diǎn):隊(duì)列中的數(shù)據(jù)元素遵循“先進(jìn)先出”(First?In?First?Out)的原則,簡稱FIFO結(jié)構(gòu)。在隊(duì)尾添加元素,在隊(duì)頭刪除元素
    2022-04-04
  • 淺析C++如何跨模塊釋放內(nèi)存

    淺析C++如何跨模塊釋放內(nèi)存

    這篇文章主要為大家詳細(xì)介紹了C++中跨模塊釋放內(nèi)存的相關(guān)知識,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以了解下
    2024-02-02
  • C語言中pthread_exit()函數(shù)實(shí)現(xiàn)終止線程

    C語言中pthread_exit()函數(shù)實(shí)現(xiàn)終止線程

    本文主要介紹了C語言中pthread_exit()函數(shù)實(shí)現(xiàn)終止線程,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • 求數(shù)組中最長遞增子序列的解決方法

    求數(shù)組中最長遞增子序列的解決方法

    本篇文章是對c++中求數(shù)組中最長遞增子序列的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • 淺談c++11線程的互斥量

    淺談c++11線程的互斥量

    互斥量是個(gè)類對象,理解成一把鎖(保護(hù)共享數(shù)據(jù),其他想操作共享數(shù)據(jù)的線程必須等待解鎖),互斥量使用要小心,保護(hù)數(shù)據(jù)不多也不少,少了則沒達(dá)到保護(hù)效果,多了則影響效率。本文將介紹c++11線程的互斥量,感興趣的同學(xué),可以參考下。
    2021-06-06
  • C++的new和delete詳解

    C++的new和delete詳解

    這篇文章主要介紹的是C++的new和delete,可以這么理解 new相當(dāng)于是malloc 、delete相當(dāng)于是free,下面我們就來詳情介紹,,需要的朋友可以參一考
    2021-09-09
  • 面試常見問題之C語言與C++的區(qū)別問題

    面試常見問題之C語言與C++的區(qū)別問題

    在C中,用static修飾的變量或函數(shù),主要用來說明這個(gè)變量或函數(shù)只能在本文件代碼塊中訪問,而文件外部的代碼無權(quán)訪問,今天重點(diǎn)給大家介紹面試中常見的C語言與C++區(qū)別的問題,感興趣的朋友跟隨小編一起看看吧
    2021-05-05
  • 深入理解C++編程中的局部變量和全局變量

    深入理解C++編程中的局部變量和全局變量

    這篇文章主要介紹了深入理解C++編程中的局部變量和全局變量,是C++入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下
    2015-09-09
  • C語言讀取寫入ini配置文件的方法實(shí)現(xiàn)

    C語言讀取寫入ini配置文件的方法實(shí)現(xiàn)

    本文主要介紹了C語言讀取寫入ini配置文件的方法實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • C語言輕松實(shí)現(xiàn)掃雷小游戲

    C語言輕松實(shí)現(xiàn)掃雷小游戲

    掃雷是一款經(jīng)典的小游戲,這篇文章主要為大家詳細(xì)介紹了C語言輕松實(shí)現(xiàn)掃雷小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08

最新評論