網站首頁 編程語言 正文
前言
C++98中的一個例子。
#include <iostream> #include <vector> #include <string> #include <algorithm> using namespace std; struct Goods { string _name; float _price; int _evaluate; Goods(const char* str, double price, int evaluate) :_name(str) , _price(price) , _evaluate(evaluate) {} }; struct PriceGreater { bool operator()(const Goods& g1, const Goods& g2) { return g1._price < g2._price; } }; struct PriceLess { bool operator()(const Goods& g1, const Goods& g2) { return g1._price > g2._price; } }; int main(void) { vector<Goods> v{ {"蘋果", 3.15, 5}, {"香蕉", 4.2, 3}, {"西瓜", 2.8, 4} }; sort(v.begin(), v.end(), PriceLess()); //按價格的降序比較 sort(v.begin(), v.end(), PriceGreater()); //按價格的升序比較 return 0; }
如果待排序的元素是自定義類型,使用sort算法排序時,需要用戶去定義仿函數類。如果每次比較邏輯不同,就需要實現不同仿函數類,這是極其不方便的。所以c++11語法增加了Lambda表達式。
lambda表達式格式
lambda表達式的格式
[捕捉列表](參數列表)mutable->返回值類型{ 語句部分 };
其中參數列表、返回值類型是可選的,捕捉列表、函數體可以為空。
先來看一個較為簡單的lamda表達式
int main(void) { auto add = [](int a, int b)->int {return a + b; }; cout << add(1, 2) << endl; return 0; }
mutable可以省略,暫時不考慮。
- 捕捉列表,捕捉列表的
[]
是千萬不能省略的,編譯器會根據[]
判斷該表達式是否為lambda表達式,捕捉列表能夠捕捉上下文的變量提供給lambda表達式使用。 - 參數列表,就和普通的函數傳參是一樣的,如果不需要參數,那么可以連同
()
一起省略 - mutable:默認情況下,lambda表達式參數列表和捕捉列表被修飾成const屬性,而mutable的作用就是取消它的const屬性。如果使用了mutable參數一定不能省略,如果參數為空,那么需要保留
()
。 - ->返回值類型。返回值類型明確或沒有返回值的情況下,該部分可省略,編譯器會對返回值類型進行推導。
- 語句部分。和不同函數的函數體內語句部分是一樣的含義,函數體內不僅可以使用它的參數,還可以使用所有捕獲到的變量。
所以最簡單的lambda表達式應該是[]{}
lambda表達式又被稱為匿名函數,無法被直接調用,它的底層其實也是仿函數類。需要借助auto將表達式賦值給一個變量。
一些語法
lambda表達式的捕捉列表不能捕捉全局變量/靜態變量
//lambda表達式的捕捉列表不能捕捉全局變量 / 靜態變量 int c = 0, d = 0; auto func1 = [c, d]() {}; int main(void) { static int a = 0; static int b = 0; auto func1 = [a, b]() {}; return 0; }
如果想要改變參數/捕捉列表,那么就需要加mutable取消const
屬性
//交換兩個變量的值,方式一: int a = 1, b = 2; auto swap1 = [](int& x, int& y)mutable {int tmp = x; x = y; y = tmp; }; swap1(a, b);
捕捉列表描述了上下文中那些數據可以被lambda使用,以及使用的方式傳值還是傳引用。
[var]:表示值傳遞方式捕捉變量var
[=]:表示值傳遞方式捕獲所有父作用域中的變量(包括this)
[&var]:表示引用傳遞捕捉變量var
[&]:表示引用傳遞捕捉所有父作用域中的變量(包括this)
[this]:表示值傳遞方式捕捉當前的this指
默認情況下,使用值傳遞的方式,捕捉到的變量被修飾成const
屬性;引用傳遞方式沒有被修飾。
函數體內使用捕捉到變量,實際上是捕捉變量的一份拷貝,所以需要對捕捉變量進行修改時,不能使用值傳遞的方式。
//交換兩個變量的值,方式二: auto swap3 = [&c, &d](){int tmp = c; c = d; d = tmp; }; swap3();
【捕捉列表注意】
同一個變量不能被同一種傳遞方式多次捕捉。捕捉的范圍:父作用域中所有的非靜態局部變量。
走進底層
調用lambda表達式的時候,先把它賦值給auto類型的對象,然后再使用()
調用。
auto的作用是自動推導右邊表達式的類型,那么lambda表達式的類型是什么?
add是一個類對象,類名為<lambda_+uuid>
,點擊此處了解uuid。
增加一個lambda表達式的調用
add(1, 2);
轉到反匯編,發現它的類里重載了()
,調用lambda表達式的底層是去調用類成員方法operator()
。
可見lambda表達式的底層就是仿函數類,所以它的調用方法也和仿函數是一樣的。
不同的lambda表達式生成的類,是不同的類。一個lambda表達式再寫一份,生成的類也是不同的,可以認為一個lambda表達式語句生成一個自己唯一的類。
//lambda表達式格式 auto add = [](int a, int b)->int {return a + b; }; add(1, 2); auto add2 = [](int a, int b)->int {return a + b; }; add2(1, 2);
因此要注意,lambda表達式之間不能相互賦值。
原文鏈接:https://blog.csdn.net/qq_56870066/article/details/126386242
相關推薦
- 2022-06-14 Qt拖放操作和打印操作的實現_C 語言
- 2022-08-28 IntelliJ IDEA 下debugger熱加載(Hot Swap)有時候失效解決
- 2022-03-28 Python實現網頁文件轉PDF文件和PNG圖片的示例代碼_python
- 2022-12-24 darknet框架中YOLOv3對數據集進行訓練和預測詳解_python
- 2023-08-30 Linux下的scp 、rsync兩種命令同步文件
- 2022-11-06 修改Nginx配置返回指定content-type的方法_nginx
- 2022-10-18 Python中尋找數據異常值的3種方法_python
- 2022-09-22 elementui select選擇器獲取選中拿到當前對象
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支