C++匿名函數

C++ 中的匿名函數(Lambda 表達式)是 C++11 引入的一項重要特性,它允許你在需要的地方定義一個臨時的、無名的函數對象,使代碼更加簡潔和靈活。

1. 基本語法

Lambda 表達式的基本結構:

[capture list](parameter list) -> return type { function body }
  • [capture list]:捕獲外部變量,指定如何將外部作用域的變量傳遞給 lambda。
  • (parameter list):參數列表,與普通函數的參數類似(可省略,但若省略括號必須為空)。
  • -> return type:返回類型(可省略,編譯器會自動推導)。
  • { function body }:函數體,包含具體的實現邏輯。

示例

auto add = [](int a, int b) -> int { return a + b; };
int result = add(3, 4);  // 結果為 7

2. 捕獲列表(Capture List)

捕獲列表用于訪問外部作用域中的變量,有以下幾種方式:

值捕獲(By Value)
  • 使用 [var] 捕獲變量的副本。
  • Lambda 創建時拷貝變量,后續修改不影響 lambda 內部的值。
int x = 10;
auto lambda = [x]() { return x * 2; };  // 捕獲 x 的值
x = 20;
std::cout << lambda();  // 輸出 20(捕獲的是 x 的副本)
引用捕獲(By Reference)
  • 使用 [&var] 捕獲變量的引用。
  • Lambda 內部使用的是變量的引用,外部修改會影響 lambda 內部。
int x = 10;
auto lambda = [&x]() { return x * 2; };  // 捕獲 x 的引用
x = 20;
std::cout << lambda();  // 輸出 40(引用 x 的當前值)
隱式捕獲
  • 使用 [=] 捕獲所有外部變量的值(值捕獲)。
  • 使用 [&] 捕獲所有外部變量的引用(引用捕獲)。
int a = 5, b = 10;
auto lambda = [=]() { return a + b; };  // 值捕獲 a 和 b
auto lambda2 = [&]() { a++; return a + b; };  // 引用捕獲 a 和 b
混合捕獲
  • 同時使用值捕獲和引用捕獲,例如 [=, &a](默認值捕獲,a 引用捕獲)。
int a = 5, b = 10;
auto lambda = [=, &a]() { a++; return a + b; };  // a 引用捕獲,b 值捕獲

3. 參數列表

Lambda 的參數列表與普通函數類似,但不支持默認參數。

auto greet = [](const std::string& name) {std::cout << "Hello, " << name << "!" << std::endl;
};
greet("Alice");  // 輸出 "Hello, Alice!"

4. 返回類型

返回類型可省略,編譯器會自動推導。若需要顯式指定,使用 -> type

auto sum = [](int a, int b) -> int { return a + b; };  // 顯式指定返回類型
auto square = [](double x) { return x * x; };  // 自動推導返回類型

5. 可變 Lambda(Mutable Lambda)

默認情況下,值捕獲的變量在 lambda 內部是只讀的。使用 mutable 關鍵字可修改值捕獲的變量。

int x = 10;
auto lambda = [x]() mutable {x++;  // 允許修改值捕獲的 xreturn x;
};
std::cout << lambda();  // 輸出 11(但外部 x 仍為 10)

6. 泛型 Lambda(C++14+)

使用 auto 作為參數類型,使 lambda 成為泛型函數。

auto print = [](const auto& value) {std::cout << value << std::endl;
};
print(42);      // 輸出整數
print("test");  // 輸出字符串

7. 捕獲 this 指針

在類成員函數中,可捕獲 this 指針以訪問類的成員變量和方法。

class MyClass {
public:int value = 10;void func() {auto lambda = [this]() { return value * 2; };std::cout << lambda();  // 輸出 20}
};

8. 捕獲初始化(C++14+)

允許在捕獲列表中初始化新變量,可移動構造對象或重命名捕獲的變量。

int x = 10;
auto lambda = [y = x + 5]() { return y; };  // 初始化 y 為 15
std::cout << lambda();  // 輸出 15// 移動捕獲(適用于不可復制的對象,如 std::unique_ptr)
auto ptr = std::make_unique<int>(42);
auto lambda2 = [ptr = std::move(ptr)]() { return *ptr; };

9. Lambda 的類型和存儲

  • Lambda 表達式的類型是一個唯一的、未命名的閉包類型(Closure Type)。
  • 可使用 autostd::function 存儲 lambda。
// 使用 auto(推薦,效率更高)
auto add = [](int a, int b) { return a + b; };// 使用 std::function(需包含 <functional>)
std::function<int(int, int)> multiply = [](int a, int b) { return a * b; };

10. Lambda 在 STL 中的應用

Lambda 常用于簡化 STL 算法的使用。

#include <algorithm>
#include <vector>std::vector<int> nums = {1, 2, 3, 4, 5};// 使用 lambda 作為謂詞
auto sum = std::accumulate(nums.begin(), nums.end(), 0, [](int acc, int x) { return acc + x; });// 排序
std::sort(nums.begin(), nums.end(), [](int a, int b) { return a > b; });  // 降序排序// 查找第一個大于 3 的元素
auto it = std::find_if(nums.begin(), nums.end(), [](int x) { return x > 3; });

11. 常量表達式 Lambda(C++17+)

使用 constexpr 關鍵字使 lambda 可以在編譯時求值。

constexpr auto add = [](int a, int b) { return a + b; };
static_assert(add(3, 4) == 7, "Error");  // 編譯時檢查

12. 模板 Lambda(C++20+)

使用模板參數(template <typename T> 的簡寫)使 lambda 更靈活。

auto lambda = []<typename T>(const T& a, const T& b) { return a + b; };
int sum_int = lambda(1, 2);        // T 推導為 int
double sum_double = lambda(1.5, 2.5);  // T 推導為 double

13. 異常規范(C++17 前)

使用 noexcept 指定 lambda 是否拋出異常。

auto safe_divide = [](double a, double b) noexcept {return b != 0 ? a / b : 0;
};

14. 性能考慮

  • Lambda 通常比普通函數指針或 std::function 更高效,因為編譯器可內聯其代碼。
  • 值捕獲會復制變量,可能影響性能(尤其是大對象),此時應優先使用引用捕獲。

總結

C++ 的匿名函數(Lambda)提供了強大而靈活的語法,使代碼更簡潔、更易讀。掌握捕獲列表、參數、返回類型和各種特性(如泛型、捕獲初始化)是使用 Lambda 的關鍵。合理使用 Lambda 可以顯著提升 C++ 代碼的表達力和效率。

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

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

相關文章

LabVIEW機械振動信號分析與故障診斷

利用 LabVIEW 開發機械振動信號分析與故障診斷系統&#xff0c;融合小波變換、時頻分布、高階統計量&#xff08;雙譜&#xff09;等先進信號處理技術&#xff0c;實現對齒輪、發動機等機械部件的非平穩非高斯振動信號的特征提取與故障診斷。系統通過虛擬儀器技術將理論算法轉化…

湖北理元理律師事務所:債務優化如何實現“減負不降質”?

在債務壓力普遍加劇的背景下&#xff0c;如何平衡債務清償與生活質量&#xff0c;成為個人及企業關注的焦點。湖北理元理律師事務所基于多年實務經驗&#xff0c;總結出一套“法律財務”雙軌制債務優化模型&#xff0c;其核心在于通過科學規劃&#xff0c;幫助債務人在法律框架…

多鏈互操作性標準解析:構建下一代區塊鏈互聯生態

引言 在區塊鏈技術快速演進的今天&#xff0c;“多鏈宇宙”已成為不可逆的趨勢。然而&#xff0c;鏈與鏈之間的孤立性導致流動性割裂、開發成本高昂和用戶體驗碎片化。互操作性標準的制定&#xff0c;正是打破這一僵局的核心鑰匙。本文將深入探討主流互操作性協議的技術架構、…

電腦開機提示按f1原因分析及解決方法(6種解決方法)

經常有網友問到一個問題,我電腦開機后提示按f1怎么解決?不管理是臺式電腦,還是筆記本,都有可能會遇到開機需要按F1,才能進入系統的問題,引起這個問題的原因比較多,今天小編在這里給大家列舉了比較常見的幾種電腦開機提示按f1的解決方法。 電腦開機提示按f1原因分析及解決…

講講git 和svn

講講git 和svn 目錄Git到底是什么&#xff1f;它該怎末用&#xff1f;核心概念基礎操作1. 倉庫的創建2. 文件的提交工作流程3. 分支管理4. 遠程倉庫操作 進階操作實際應用建議**基本用法****常用命令的幫助示例****幫助文檔的結構****替代方法****練習建議****核心概念****與Gi…

【行為型之中介者模式】游戲開發實戰——Unity復雜系統協調與通信架構的核心秘訣

文章目錄 &#x1f54a;? 中介者模式&#xff08;Mediator Pattern&#xff09;深度解析一、模式本質與核心價值二、經典UML結構三、Unity實戰代碼&#xff08;成就系統協調&#xff09;1. 定義中介者接口與同事基類2. 實現具體同事類3. 實現具體中介者4. 客戶端使用 四、模式…

【網工第6版】第10章 網絡規劃和設計②

目錄 ■ 網絡分析與設計 ◆ 網絡規劃設計模型 ◆ 網絡設計的約束因素 ◆ 技術評價 ■ 網絡結構與功能 ◆ 局域網結構類型 ■ 網絡冗余設計 ◆ 網絡冗余設計-備用路徑 ◆ 網絡冗余設計-負載分擔 ■ 廣域網接入技術 ◆ 廣域網接入技術 ◆ 接入和終結設備 ■ 網絡分析…

PowerBI鏈接EXCEL實現自動化報表

PowerBI鏈接EXCEL實現自動化報表 曾經我將工作中一天的工作縮短至2個小時&#xff0c;其中最關鍵的一步就是使用PowerBI鏈接Excel做成一個自動化報表&#xff0c;PowerBI更新源數據&#xff0c;Excel更新報表并且保留報表格式。 以制作一個超市銷售報表為例&#xff0c;簡單敘…

C#.NET 或 VB.NET Windows 窗體中的 DataGridView – 技巧、竅門和常見問題

DataGridView 控件是一個 Windows 窗體控件&#xff0c;它允許您自定義和編輯表格數據。它提供了許多屬性、方法和事件來自定義其外觀和行為。在本文中&#xff0c;我們將討論一些常見問題及其解決方案。這些問題來自各種來源&#xff0c;包括一些新聞組、MSDN 網站以及一些由我…

表記錄的檢索

1.select語句的語法格式 select 字段列表 from 表名 where 條件表達式 group by 分組字段 [having 條件表達式] order by 排序字段 [asc|desc];說明&#xff1a; from 子句用于指定檢索的數據源 where子句用于指定記錄的過濾條件 group by 子句用于對檢索的數據進行分組 ha…

能源設備數據采集

在全球可持續發展目標與環境保護理念日益深入人心的時代背景下&#xff0c;有效管理和優化能源使用已成為企業實現綠色轉型、提升競爭力的關鍵路徑。能源設備數據采集系統&#xff0c;作為能源管理的核心技術支撐&#xff0c;通過對各類能源生產設備運行數據的全面收集、深度分…

【鴻蒙開發】性能優化

語言層面的優化 使用明確的數據類型&#xff0c;避免使用模糊的數據類型&#xff0c;例如ESObject。 使用AOT模式 AOT就是提前編譯&#xff0c;將字節碼提前編譯成機器碼&#xff0c;這樣可以充分優化&#xff0c;從而加快執行速度。 未啟用AOT時&#xff0c;一邊運行一邊進…

群暉NAS部署PlaylistDL音樂下載器結合cpolar搭建私有云音樂庫

文章目錄 前言1.關于PlaylistDL音樂下載器2.Docker部署3.PlaylistDL簡單使用4.群暉安裝Cpolar工具5.創建PlaylistDL音樂下載器的公網地址6.配置固定公網地址總結 前言 各位小伙伴們&#xff0c;你們是不是經常為了聽幾首歌而開通各種平臺的VIP&#xff1f;或者為了下載無損音質…

REST架構風格介紹

一.REST&#xff08;表述性狀態轉移&#xff09; 1.定義 REST&#xff08;Representational State Transfer&#xff09;是由 Roy Fielding 在 2000 年提出的一種軟件架構風格&#xff0c;用于設計網絡應用的通信模式。它基于 HTTP 協議&#xff0c;強調通過統一的接口&#…

計算機視覺----基于錨點的車道線檢測、從Line-CNN到CLRNet到CLRKDNet 本文所提算法Line-CNN 后續會更新以下全部算法

本文所提算法如下&#xff1a; 敘述按時間順序 你也可以把本文當作快速閱讀這幾篇文獻的一個途徑 所有重要的部分我都已經標注并弄懂其原理 方便自己也是方便大家 Line-CNN&#xff1a;基于線提議單元的端到端交通線檢測 摘要 交通線檢測是一項基礎且具有挑戰性的任務。以往的…

一.android Studio開發系統應用——導入TvSettings源碼

目標 最終效果如上,實現在AS中編輯源碼后一鍵在真機中運行。達到和普通應用開發一樣的調試和編碼過程。這種方法可以大幅度提升開發速度,但是導入過程確實相對繁瑣和消耗時間。適合需要精細或者頻繁改動的系統app源碼。 一、新建項目 包名:com.android.tv.settings 版本:…

20250515讓飛凌的OK3588-C的核心板在Linux R4下適配以太網RTL8211F-CG為4線百兆時的接線圖

20250515讓飛凌的OK3588-C的核心板在Linux R4下適配以太網RTL8211F-CG為4線百兆時的接線圖 2025/5/15 20:19 緣起&#xff1a;以前做的網線找不到了&#xff0c;那就再來一條吧。 引腳定義要從頭來過&#xff1f;還好找到了一條。 開干&#xff01; 萬用表一對/點&#xff0c;幾…

【技術原理】Linux 文件時間屬性詳解:Access、Modify、Change 的區別與聯系

在 Linux 系統中&#xff0c;每個文件都有三個核心時間屬性&#xff1a;Access Time (atime)、Modify Time (mtime) 和 Change Time (ctime)。它們分別記錄文件不同維度的變更信息&#xff0c;以下是具體區別與聯系&#xff1a; 一、定義與觸發條件 時間屬性定義觸發條件示例A…

乘法口訣練習神器

請你利用python語言開發一個“乘法口訣練習神器”&#xff0c;主要輔助小學生練習乘法口訣&#xff0c;主要功能如下&#xff1a; 1. 能夠隨機循環出10道題&#xff0c;可以是乘法或者是除法。如果是乘法&#xff0c;確保兩個因數都是1-9之間的整數&#xff1b;如果是除法&…

[c語言日寄]數據結構:棧

【作者主頁】siy2333 【專欄介紹】?c語言日寄?&#xff1a;這是一個專注于C語言刷題的專欄&#xff0c;精選題目&#xff0c;搭配詳細題解、拓展算法。從基礎語法到復雜算法&#xff0c;題目涉及的知識點全面覆蓋&#xff0c;助力你系統提升。無論你是初學者&#xff0c;還是…