最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深入理解C++11:探索lambda函數的奧秘

 更新時間:2024年01月19日 08:31:39   作者:春人.  
聚焦于C++11,讓我們一起探索lambda函數的奧秘,本指南將帶您深入了解這個強大的編程工具,讓您在編程世界中如虎添翼,無論您是初學者還是有經驗的開發(fā)者,本指南都將為您帶來全新的視角和實用的技巧,需要的朋友可以參考下

一、C++98中的排序

在 C++98 中,如果要對一個數據集合中的元素進行排序,可以使用 std::sort 方法,下面代碼是對一個整型集合進行排序。

#include <algorithm>
#include <functional>
#include <iostream>
using namespace std;
int main()
{
	int array[] = { 4,1,8,5,3,7,0,9,2,6 }; 
	cout << "原始數組:";
	for (auto e : array)
	{
		cout << e << ' ';
	}
	cout << endl << endl << "排升序:";
	// 默認按照小于比較,排出來結果是升序
	std::sort(array, array + sizeof(array) / sizeof(array[0]));
	for (auto e : array)
	{
		cout << e << ' ';
	}
	cout << endl << endl << "排降序:";
	// 如果需要降序,需要改變元素的比較規(guī)則
	std::sort(array, array + sizeof(array) / sizeof(array[0]), greater<int>());

	for (auto e : array)
	{
		cout << e << ' ';
	}
	return 0;
}

在這里插入圖片描述

小Tips:上面的 greater 是一個仿函數,這里傳遞仿函數是用來控制大小比較的。關于仿函數,在前面的文章中已經多次使用,在【C++雜貨鋪】優(yōu)先級隊列的使用指南與模擬實現一文中,我們使用仿函數來進行大小比較;在【C++雜貨鋪】一文帶你走進哈希:哈希沖突 | 哈希函數 | 閉散列 | 開散列一文中,我們使用仿函數來獲取 pair<K, V> 模型中的 key??傊?,仿函數有著十分強大的功能。

如果待排序的元素為自定義類型,由于自定義類型中可能有多重不同的屬性,因此需要用戶自己來定義排序時的比較規(guī)則:

struct Goods
{
	string _name;  // 名字
	double _price; // 價格
	int _evaluate; // 評價
	Goods(const char* str, double price, int evaluate)
		:_name(str)
		, _price(price)
		, _evaluate(evaluate)
	{}
};

ostream& operator<<(ostream& out, Goods& goods)
{
	out << goods._name << '-' << goods._price << '-' << goods._evaluate;

	return out;
}

struct ComparePriceLess
{
	bool operator()(const Goods& gl, const Goods& gr)
	{
		return gl._price < gr._price;
	}
};
struct ComparePriceGreater
{
	bool operator()(const Goods& gl, const Goods& gr)
	{
		return gl._price > gr._price;
	}
};

struct CompareevaluateLess
{
	bool operator()(const Goods& gl, const Goods& gr)
	{
		return gl._evaluate < gr._evaluate;
	}
};
struct CompareevaluateGreater
{
	bool operator()(const Goods& gl, const Goods& gr)
	{
		return gl._evaluate > gr._evaluate;
	}
};
int main()
{
	vector<Goods> v = { { "蘋果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2,
   3 }, { "菠蘿", 1.5, 4 } };
	cout << "排序前:";
	for (auto e : v)
	{
		cout << e << ' ';
	}
	cout << endl << endl << "按照價格排升序:";
	sort(v.begin(), v.end(), ComparePriceLess());
	for (auto e : v)
	{
		cout << e << ' ';
	}
	cout << endl << endl << "按照價格排降序:";
	sort(v.begin(), v.end(), ComparePriceGreater());
	for (auto e : v)
	{
		cout << e << ' ';
	}
	cout << endl << endl << "按照評價排升序:";
	sort(v.begin(), v.end(), CompareevaluateLess());

	for (auto e : v)
	{
		cout << e << ' ';
	}
	cout << endl << endl << "按照評價排降序:";

	sort(v.begin(), v.end(), CompareevaluateGreater());

	for (auto e : v)
	{
		cout << e << ' ';
	}
	cout << endl;
}

在這里插入圖片描述

小Tips:上面代碼中如果要使用庫里面的仿函數 lessgreater,需要對 >、< 進行運算符重載,實現 Goods 類的大小比較。但是上面的代碼中并沒有采取這種做法,而是直接自己寫了兩個仿函數進行大小關系的比較。前面那種提供運算符重載的方法比較局限,因為無論是 < 還是 > 都只能重載一份,即 operator<operator> 各自只能在代碼中出現一份,且它們的內部只能根據一種屬性進行大小比較,在同一段代碼中不能實現根據不同屬性去排序。而自己寫仿函數就不會出現這種情況,我們可以在同一段代碼中根據不同的屬性去寫不同的仿函數(只要類名不同即可)。

隨著 C++ 語法的發(fā)展,人們開始覺得上面的寫法太復雜了,每次為了實現一個排序算法,都要重新去寫一個類(仿函數,實現大小比較),如果每次比較的邏輯不一樣,還要去實現多個類,特別是相同類的命名,這些都給編程者帶來了極大的不便。因此,在 C++11 語法中出現了 Lambda 表達式。

二、先來看看 lambda 表達式長什么樣

struct Goods
{
	string _name;  // 名字
	double _price; // 價格
	int _evaluate; // 評價
	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 } };
	cout << "排序前:";
	for (auto e : v)
	{
		cout << e << ' ';
	}

	cout << endl << endl << "按照價格排升序:";
	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2)->bool {return g1._price < g2._price; });
	for (auto e : v)
	{
		cout << e << ' ';
	}

	cout << endl << endl << "按照價格排降序:";
	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2)->bool {return g1._price > g2._price; });
	for (auto e : v)
	{
		cout << e << ' ';
	}

	cout << endl << endl << "按照評價排升序:";
	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2)->bool {return g1._evaluate < g2._evaluate; });
	for (auto e : v)
	{
		cout << e << ' ';
	}

	cout << endl << endl << "按照評價排降序:";
	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2)->bool {return g1._evaluate > g2._evaluate; });
	for (auto e : v)
	{
		cout << e << ' ';
	}

	cout << endl;
}

在這里插入圖片描述

小Tips:上述代碼就是使用 C++11 中的 lambda 表達式來解決,可以看出 lambda 表達式實際是一個匿名函數對象。

三、lambda表達式語法

lambda 表達式書寫格式為:[capture-list](parameters) mutable-> return-type {statement}。

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

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

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

->returntype:返回值類型。用追蹤返回類型形式聲明函數的返回值類型,沒有返回值時此部分可以省略。返回值類型明確的情況下,也可以省略,由編譯器對返回值類型進行推斷。

{statement}:函數體。在該函數體內,除了可以使用其參數外,還可以使用所有捕捉到的變量。

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

實例:

int AddFunc(int x, int y)
{
	return x + y;
}

int num1 = 10, num2 = 20;

int main()
{
	// 實現兩個數相加的 lambda 函數
	int a = 1, b = 10;
	auto add = [](int x, int y)->int {return x + y; };
	cout << add(a, b) << endl;

	// 實現兩個函數交換的 lambda 函數
	auto swap = [add, a, b](int& x, int& y)
	{
		int tmp = x;
		x = y;
		y = tmp;

		// cout << add(a, b) << endl; // 在 lambda 函數的函數體中無法直接使用局部的 lambda 函數或者變量(對象).
		//cout << AddFunc(a, b) << endl; // 在 lambda 函數的函數體中可以直接使用全局的函數或者變量(對象).
		cout << AddFunc(num1, num2) << endl; // 在 lambda 函數的函數體中可以直接使用全局的函數或者變量(對象).
	};

	swap(a, b);
	return 0;
}

小Tips:在 lambda 函數的函數體中可以調用全局的函數,使用全局的變量。但是要想在 lambda 的函數體中使用局部的變量或對象,則需要通過捕捉列表或者參數列表。

3.1 捕捉列表的使用細節(jié)

捕捉列表描述了上下文中哪些數據可以被 lambda 使用,以及使用的方式是傳值還是傳引用。

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

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

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

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

[this]:表示值傳遞方式捕捉當前的 this 指針。

小Tips:

父作用域指包含 lambda 函數語句塊的作用域。

值傳遞方式捕捉到的變量本質上是父作用域中變量的一份拷貝,在默認情況下會對捕捉到的變量加上 const 屬性,即不可以在 lambda 函數體中對捕捉到的變量進行修改。如果想修改可以加上 mutable 取消其常量性。即 [x, y] 捕捉列表中的 xy 是父作用域中 xy 的一份拷貝,并且默認給捕捉列表中的 xy 加上了 const 屬性。

引用傳遞方式既可以捕捉普通的變量也可以捕捉 const 變量。

語法上捕捉列表可以由多個捕捉項組成,并以逗號隔開。例如:[=, &a, &b]:以引用傳遞的方式捕捉變量 ab,以值傳遞方式捕捉其他所有變量;[&, a, this]:以值傳遞方式捕捉變量 athis,以引用方式捕捉其他變量。如果由多個捕捉項組成,=& 只能出現在捕捉列表的開頭,即 [&a, &b, = ] 這樣寫是錯誤的。

捕捉列表不允許變量重復傳遞,否則就會導致編譯出錯。例如:[=, a]:= 已經以值傳遞的方式捕捉了所有變量,在去捕捉 a 就會導致重復捕捉。

在塊作用域以外的 lambda 函數捕捉列表必須為空。

在塊作用域中的 lambda 函數僅能捕捉父作用域中的局部變量,捕捉任何非此作用域或者 非局部變量都會導致編譯報錯。

lambda 表達式之間不能相互賦值,即使看起來類型相同。

四、lambda 的底層原理

lambda 看起來很厲害,但它本質上就是仿函數。

int main() 
{
	auto func1 = [](int x, int y) {return x + y; };
	auto func2 = [](int x, int y) {return x + y; };

	cout << typeid(func1).name() << endl;
	cout << typeid(func2).name() << endl;

	func1(1, 2);
	return 0;
}

在這里插入圖片描述

如上面代碼所示,兩個仿函數對象 func1func2 它們看起來是一模一樣的,但是通過打印它們各自的類型可以看出,它們的類型有所不同,因此 func1func2 本質上就是兩個不同的類對象,所以 lambda 表達式之間不能相互賦值,即使看起來類型相同。func1(1, 2) 本質上就是 func1 這個仿函數的對象在調用 operator()。

在這里插入圖片描述

到此這篇關于深入理解C++11:探索lambda函數的奧秘的文章就介紹到這了,更多相關C++11 lambda函數內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • C語言常用占位符的使用小結

    C語言常用占位符的使用小結

    占位符是一種用于格式化輸出的特殊字符,通常用于 printf() 等輸出函數中,本文主要介紹了C語言常用占位符的使用小結,非常具有實用價值,需要的朋友可以參考下
    2023-05-05
  • C語言中的狀態(tài)機設計深入講解

    C語言中的狀態(tài)機設計深入講解

    這篇文章主要給大家介紹了關于C語言狀態(tài)機設計的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-11-11
  • c語言全盤搜索指定文件的實例代碼

    c語言全盤搜索指定文件的實例代碼

    c語言全盤搜索指定文件的實例代碼,需要的朋友可以參考一下
    2013-03-03
  • opencv3機器學習之EM算法示例詳解

    opencv3機器學習之EM算法示例詳解

    這篇文章主要介紹了opencv3機器學習之EM算法的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • 初學C++之自定義類型名簡化詳解

    初學C++之自定義類型名簡化詳解

    下面小編就為就大家?guī)硪黄鯇WC++之自定義類型名簡化詳解。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-09-09
  • C++中md5 算法實現代碼

    C++中md5 算法實現代碼

    在網上找了份c++ MD5的代碼,就簡單保存一下,需要的朋友可以參考下
    2017-07-07
  • 基于C語言實現猜數字游戲

    基于C語言實現猜數字游戲

    這篇文章主要為大家詳細介紹了基于C語言實現猜數字游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • C語言函數的參數使用指針

    C語言函數的參數使用指針

    這篇文章主要介紹了C語言函數的參數使用指針,本文講述了指針在作為函數參數時候的使用方法,解析值傳遞和值引用的區(qū)別案例,希望對你有所幫助
    2021-06-06
  • 解析C++編程中的繼承方面的運用

    解析C++編程中的繼承方面的運用

    這篇文章主要介紹了解析C++編程中的繼承方面的運用,是C++入門學習中的基礎知識,需要的朋友可以參考下
    2015-09-09
  • C++實現strcmp字符串比較的深入探討

    C++實現strcmp字符串比較的深入探討

    本篇文章是對使用C++實現strcmp字符串比較進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05

最新評論

通河县| 涟水县| 通辽市| 离岛区| 六盘水市| 四会市| 兖州市| 卓资县| 平和县| 青铜峡市| 航空| 柏乡县| 朝阳市| 永丰县| 布尔津县| 台湾省| 闽侯县| 定西市| 溧水县| 清水县| 陆川县| 道真| 通江县| 德令哈市| 偃师市| 浑源县| 延寿县| 沂水县| 镇赉县| 滨海县| 南江县| 攀枝花市| 额敏县| 平江县| 桃江县| 雷州市| 广宗县| 蒙自县| 扶绥县| 武陟县| 华池县|