C++11 lambda

前言

在Cpp11以前,為了把函數當作對象調用,可以使用C中的函數指針類型,也可以使用Cpp98的仿函數。

但二者都不是很好用,函數指針 return_type (*name)(parameters)的長相就令人望而卻步,仿函數將一個函數重載為一個類的operator()的方式又沉重麻煩。

C++11中做出了(抄Python的)更靈活、輕便的lambda表達式。

lambda表達式

lambda表達式 是一個 匿名函數對象,本質上是一個對象。

語法格式

[capture_list](parameters)->return_type
{};

由捕捉列表、參數列表、返回值、函數體四大部分構成。

捕捉列表用于捕捉此前出現過的變量,后三大部分就是函數正常的定義理解。(如果函數無參且無返回值,可以省略這兩大部分,但是捕捉列表和函數體不可省略)

捕捉列表?

由于lambda本質是一個對象,在寫出lambda表達式時,就在創建一個對象。

捕捉列表中捕捉的值,就是構造函數的參數,用于初始化成員變量,以供函數體中直接使用。

捕捉的規則如下:

【1】捕捉某變量的值

int a = 1, b = 2;
auto afun = [a](){cout << a << endl;
}
auto abfun = [a, b](int x, int y){cout << a + b << endl;
}

此時,捕捉a、b值,相當于拷貝a、b的值,lambda中的a、b和外面的變量a、b是兩個東西。

且lambda內部不能修改捕捉的變量值,會報錯。(硬要修改就要了解mutable關鍵字)

【2】捕捉某變量的引用

要捕捉變量引用,就在捕捉列表中,變量前加上一個&。

int a = 0;
auto af = [&a](){a++;cout<< a << endl;
};

此時的變量a就是內外統一的了,允許修改了。?

【3】捕捉所有變量的值

int a = 0, b = 1, c = 2, d = 3;auto all_fun = [=]{           //捕捉所有要用到的變量值cout << a+b+c+d << endl;
};auto all_fun = [=, &a]{       //在=后指定需要引用的變量a++;cout << a+b+c+d << endl;
};

前者用 = 表示?捕捉所有要用到的變量值;后者在?= 后指定需要引用的變量。

【4】捕捉所有變量的引用

int a = 0, b = 1, c = 2, d = 3;auto r_fun_1 = [&]{a++;b++;c++;
};
auto r_fun_2 = [&, a]{b++;c++;d++;
};

用&表示捕獲所有被使用的變量的引用;后者指定捕獲某變量的值。

補充

【1】全局變量不需要捕捉,也不能。

【2】返回值可以不寫,函數體內部返回值時,編譯器會自己推。但建議寫,為了代碼的可讀性。

【3】使用auto可以推導lambda的類型,這個類型由編譯器決定,MSVC用uuid來保證不同的lambda有不同的類型。這樣匿名函數對象就可以被引用了,延長了生命周期,可以直接作為一個函數使用。(模板也能推)

應用場景

在使用算法庫中的sort排序時,有時想要按照特殊的要求進行排序,就要傳仿函數對象。

現在,我們可以直接傳lambda匿名函數對象即可,輕便易讀。可以替換仿函數的大部分使用。

包裝器

function和bind都在<functional>頭文件中。

function類模板

template <class T> function;     // undefinedtemplate <class Ret, class... Args> class function<Ret(Args...)>;

?function包裝器一般用于包裝返回值、參數列表的函數對象。包裝前進行特化即可。

用函數的返回值和參數類型進行特化:Ret是前者類型,可變參數包Args是后者。

int pf(int a, int b)
{return a + b;
}struct Functor
{int operator()(int a, int b){return a - b;}
};int main()
{auto lf = [](int a, int b) { return a * b; };function<int(int, int)> f1 = &pf; //函數名也行,也是函數指針function<int(int, int)> f2 = lf;function<int(int, int)> f3 = Functor();vector<function<int(int, int)>> funcs = { f1, f2, f3 };//非靜態成員函數                       function<int(Functor*, int, int)> f4 = &Functor::operator();function<int(Functor&&, int, int)> f5 = &Functor::operator();Functor f1_obj;f4(&f1_obj, 5, 6);f5(Functor(), 5, 6);return 0;
}

通過上例可見,用function包裝了函數指針,lambda函數對象,仿函數對象。?

?這樣統一了他們的類型,最后竟能放在一個容器里。

特殊的地方在于下面的非靜態成員函數的包裝。由于成員函數有一個隱式的參數--this指針,所以其特化類型與上面不同,但既可以傳引用,也可以傳指針。

在調用時,也要手動傳入對象的指針或者對象。

這個就需要回顧類和對象重載運算符 .* 和 ->* 的知識點。但對比一下,可以看出,函數指針真的不方便,不如包裝器好用。

	typedef int(Functor::*PF)(int, int);PF pf = &Functor::operator(); //成員函數指針必須加&才能取到//int(Functor::*)(int, int) p = &Functor::operator();//cpp不允許這樣寫和用函數指針類型Functor f;(f.*pf)(5, 6);Functor* p = &f;(p->*pf)(5, 6);

bind函數模板

在了解了function的包裝類型后,bind的作用就不太一樣。

bind主要用于函數的參數個數或位置調整。需要結合placeholders命名空間中的_1、_2、...、_n的占位符使用。

template <class Fn, class... Args>/* unspecified */ bind (Fn&& fn, Args&&... args);template <class Ret, class Fn, class... Args>/* unspecified */ bind (Fn&& fn, Args&&... args);

?使用:把要調整的函數的包裝后的對象傳給bind,使用占位符進行調整。

調整參數位置

using namespace placeholders;
int main()
{auto fun = [](int a, int b) { return a + b*10; };auto newFun = bind(fun, _2, _1);cout << fun(3, 4) << endl;     //43cout << newFun(3, 4) << endl;  //34return 0;
}

bind中的占位符用來確定實參的位置,根據實參所在位置從左往右確定_1、_2等等。然后bind再將對應占位符的值傳給原本的函數。以實現參數位置的調整。

調整參數個數

通過確定某個位置的值,以達到少傳參數、調整參數個數的目的。

auto newFun_4 = bind(fun, _1, 4);cout << newFun_2(3) << endl;  // 3 + 4 * 10;

強調:占位符指的是實參的位置。。。不要搞混了。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/86470.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/86470.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/86470.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【國產化-K8s】混合架構的 K8s + KubeSphere 部署指南

本文由 KubeSphere 社區貢獻者 天行1st 編寫。本文為作者實踐總結。本文記錄了在信創環境中基于混合架構&#xff08;x86 與 ARM64&#xff09;部署 Kubernetes 和 KubeSphere 的實踐過程&#xff0c;覆蓋多種國產 CPU 和操作系統&#xff0c;具有一定的參考價值。 環境涉及軟…

利用python實現NBA數據可視化

大家好&#xff0c;今天我們利用python爬取NBA球星每年的比賽數據并進行可視化展示。主要用到三個模塊&#xff1a;xpath、matplotlib。其中xpth負責爬取網站上的信息。Matplotlib是Python開發人員常用的Python繪圖庫&#xff0c;可以用來繪制各種2D圖形&#xff0c;具有繪圖質…

基于 SpringBoot+JSP 的醫療預約與診斷系統設計與實現

摘要 本研究針對傳統醫療預約與診斷流程中存在的效率低下、信息不透明、患者等待時間長等問題&#xff0c;設計并實現了一個基于 SpringBootJSP 的醫療預約與診斷系統。系統采用 B/S 架構&#xff0c;整合了用戶管理、科室管理、醫生排班、預約掛號、在線問診、檢查檢驗、診斷…

2025.6.27總結

最近工作又開始內耗了&#xff0c;一位同事的轉崗直接讓我破防了&#xff0c;明明他工作干得很不錯&#xff0c;會得又多&#xff0c;性格又好&#xff0c;我還經常請教他業務上的問題。我和他的關系并不算太好&#xff0c;但他加入其他部門&#xff0c;竟然讓我有些不舍&#…

詳解HashMap底層原理

核心數據結構&#xff1a;數組 鏈表 / 紅黑樹 HashMap 的底層核心是一個 Node<K,V>[] table 數組&#xff08;通常稱為 桶數組 或 哈希桶數組&#xff09;。這個數組的每個元素稱為一個 桶。 Node<K,V> (鏈表節點)&#xff1a; 這是存儲鍵值對的基本單位&#xf…

歷史項目依賴庫Bugfix技巧-類覆蓋

在項目維護過程中&#xff0c;我們可能會遇到歷史項目依賴的第三方庫出現BUG而需要修復的情況&#xff0c;而這些第三方庫可能來源于公司自主開發或開源項目&#xff0c;但由于各種原因&#xff0c;這些庫可能已無人維護。 此時&#xff0c;解決這個問題有三個辦法 1、基于源…

多模態大型語言模型最新綜述

多模態大型語言模型&#xff08;Multimodal Large Language Models&#xff0c;MLLMs&#xff09;已迅速發展&#xff0c;超越了文本生成的范疇&#xff0c;如今能夠覆蓋圖像、音樂、視頻、人類動作以及三維物體等多種輸出模態。它們通過在統一架構下將語言與其他感知模態整合&…

使用ASIO的協程實現高并發服務器

使用ASIO的協程實現高并發服務器 在 C 網絡編程領域&#xff0c;Asio 庫提供了兩種主要的異步編程范式&#xff1a;傳統的回調模式和基于協程的現代模式&#xff0c;傳統的回調模式大家都很清楚&#xff0c;這里不多做介紹&#xff0c;本文主要介紹基于協程的模式&#xff0c;…

OpenCV——輪廓檢測

輪廓檢測 一、輪廓檢測二、輪廓的層級三、輪廓的特征3.1、輪廓面積3.2、輪廓周長3.3、邊界矩形3.4、最小外接圓3.5、近似輪廓3.6、凸包 一、輪廓檢測 輪廓可以簡單的描述為具有相同顏色或灰度的連續點連在一起的一條曲線&#xff0c;輪廓通暢會顯示出圖像中物體的形狀。關于輪…

高等概率論題解-心得筆記【15】

文章目錄 拓撲參考文獻 拓撲 參考文獻 《測度論基礎與高等概率論》

Windows 10關閉自動更新功能

Windows 10關閉自動更新功能&#xff0c;大家是不是經常用下面的幾個步驟&#xff1a; 1、禁用Windows Update服務&#xff1b; 2、在組策略里關閉Win10自動更新相關服務&#xff1b; 3、禁用任務計劃里邊的Win10自動更新&#xff1b; 4、在注冊表中關閉Win10自動更新&…

[Meetily后端框架] 配置指南 | 后端API網關 | API文檔體系

鏈接: https://github.com/Zackriya-Solutions/meeting-minutes docs&#xff1a;會議紀要管理系統 本項目是一個專門用于**處理會議記錄**的后端系統。 系統接收會議文本內容&#xff0c;利用先進的AI模型自動識別關鍵信息&#xff0c;包括行動項、決策內容以及截止期限。 處…

Flink2.0 配置 historyserver

Flink2.0 配置 historyserver 主要是去修改config.yaml配置文件 主要修改的點有兩個 網上很多文檔都是寫的只配置一個 都是坑啊 historyserver :歷史服務器 運行 Flink job 的集群一旦停止(例如yarn模式&#xff0c;程序一旦停止&#xff0c;集群也就關閉了)&#xff0c;只能去…

LLM的訓練過程

一般而言&#xff0c;訓練一個完整的 LLM 需要經過圖1中的三個階段——Pretrain、SFT 和 RLHF。 1.預訓練 Pretrain&#xff0c;即預訓練&#xff0c;是訓練 LLM 最核心也是工程量最大的第一步。LLM 的預訓練和傳統預訓練模型非常類似&#xff0c;同樣是使用海量無監督文本對隨…

用 AI + Canvas 生成圖形、動畫與圖表

摘要 隨著人工智能&#xff08;AI&#xff09;技術與 Web 可視化的結合&#xff0c;前端開發者可以通過自然語言生成復雜的圖表、動畫和交互式畫布&#xff0c;極大地提升了開發效率和用戶體驗。本文作為《AI 前端&#xff1a;構建智能化 Web 應用的未來》專欄的第七篇&#…

SQL Server for Linux 如何實現高可用架構

關鍵詞&#xff1a;SQL Server for Linux、高可用、讀寫分離、動態擴容、Always On、可用性組 &#x1f4cb; 文章目錄 前言&#xff1a;Linux上的SQL Server不再是夢高可用架構設計 Always On 可用性組故障轉移集群實例 讀寫分離架構 可用性組讀寫分離應用層讀寫分離 動態擴…

【51單片機流水燈控制4種造型,按下1,2,3,4時,數碼管對應顯示鍵號,同時流水燈對應四種造型】2022-6-1

緣由流水燈控制4種造型&#xff0c;按下1,2,3,4時&#xff0c;數碼管對應顯示鍵號&#xff0c;同時流水燈對應四種造型-編程語言-CSDN問答 #include "REG52.h" unsigned char code smgduan[]{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5…

設計模式 - 工廠方法

工廠方法是一種設計模式&#xff0c;對工廠制造方法進行接口規范化&#xff0c;允許子類工廠決定具體知道哪類產品的實例&#xff0c;最終降低系統耦合&#xff0c;使系統的可維護性、可擴展性等得到提升。 一、工廠的多元化與專業化 要實例化對象&#xff0c;就得用到關鍵詞“…

數據應該如何組織,才能讓Excel“讀懂”?

前言&#xff1a;如果你希望Excel能“讀懂”你的數據&#xff0c;就得學會讓排序、篩選、數據透視表、函數等這些功能為我們服務。 假設你在和一個非常聰明但有點“死板”的機器人&#xff08;Excel&#xff09;對話&#xff0c;你必須用它能理解的語言來組織信息。 “一維表”…

js防止重復提交的3種解決方案

防止 javascript 重復點擊和提交的關鍵方法有三種&#xff1a;1. 禁用按鈕法&#xff0c;點擊后立即禁用按鈕并更改文本提示&#xff0c;請求完成后恢復&#xff1b;2. 節流函數&#xff08;throttle&#xff09;&#xff0c;限制函數在設定時間間隔內僅執行一次&#xff0c;適…