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

C++?lambda?匿名函數(shù)深入解析

 更新時(shí)間:2025年09月19日 09:03:49   作者:xclic  
C++11引入的lambda匿名函數(shù)(Lambda?Expression)是一種輕量級(jí)的函數(shù)對(duì)象,可在需要函數(shù)的地方直接定義,無(wú)需單獨(dú)聲明,極大簡(jiǎn)化了代碼編寫,本文給大家介紹C++?lambda?匿名函數(shù)的相關(guān)知識(shí),感興趣的朋友一起看看吧

1、基本介紹

C++11 引入的 lambda 匿名函數(shù)(Lambda Expression)是一種輕量級(jí)的函數(shù)對(duì)象,可在需要函數(shù)的地方直接定義,無(wú)需單獨(dú)聲明,極大簡(jiǎn)化了代碼編寫(尤其是回調(diào)函數(shù)、算法謂詞等場(chǎng)景)。

基本語(yǔ)法:

[capture-list] (parameter-list) mutable noexcept(optional) -> return-type { function-body }
組成部分說(shuō)明
capture-list捕獲列表:指定如何捕獲 lambda 所在作用域的局部變量(值捕獲、引用捕獲等),不可省略。
parameter-list參數(shù)列表:與普通函數(shù)的參數(shù)列表一致(可省略,若無(wú)形參)。
mutable可選關(guān)鍵字:允許在 lambda 內(nèi)部修改值捕獲的變量(默認(rèn)值捕獲變量為 const)。
noexcept可選:指定 lambda 是否可能拋出異常(C++11 起)。
-> return-type返回類型可選,若函數(shù)體僅有一條 return 語(yǔ)句,編譯器可自動(dòng)推導(dǎo)返回類型。
function-body函數(shù)體:lambda 的執(zhí)行邏輯。

簡(jiǎn)單的例子

#include <iostream>
#include <vector>
#include <algorithm>
int main() {
    std::vector<int> v = {3, 1, 4, 1, 5, 9, 2, 6};
    // 使用 Lambda 表達(dá)式作為 std::sort 的比較準(zhǔn)則
    // 按降序排序
    std::sort(v.begin(), v.end(), 
              [](int a, int b) { return a > b; } // Lambda 表達(dá)式
             );
    for (int i : v) {
        std::cout << i << " ";
    }
    // 輸出: 9 6 5 4 3 2 1 1
    return 0;
}

2、捕獲列表

捕獲列表定義了 Lambda 表達(dá)式如何從其所在的作用域中訪問(wèn)外部變量。

2.1 值捕獲

將外部變量的值拷貝到 Lambda 中。Lambda 內(nèi)部修改不會(huì)影響外部變量。

int main() {
    int x = 10;
    int y = 20;
    // 值捕獲:將 x 和 y 的當(dāng)前值拷貝到 Lambda 中
    auto lambda_val = [x, y]() { 
        std::cout << "Inside lambda (by value): " << x << ", " << y << std::endl;
        // x++; // 錯(cuò)誤!默認(rèn)情況下,值捕獲的變量是 const 的。
    };
    x = y = 100; // 修改外部變量
    lambda_val(); // 調(diào)用 Lambda
    // 輸出: Inside lambda (by value): 10, 20
    return 0;
}

2.2 引用捕獲

捕獲外部變量的引用。Lambda 內(nèi)部修改會(huì)直接影響外部變量。

int main() {
    int x = 10;
    int y = 20;
    // 引用捕獲:捕獲 x 和 y 的引用
    auto lambda_ref = [&x, &y]() { 
        std::cout << "Inside lambda (by ref): " << x << ", " << y << std::endl;
        x++; y++; // 修改會(huì)影響外部變量
    };
    lambda_ref(); // 調(diào)用 Lambda
    std::cout << "After lambda: " << x << ", " << y << std::endl;
    // 輸出: 
    // Inside lambda (by ref): 10, 20
    // After lambda: 11, 21
    return 0;
}

2.3 隱式捕獲

讓編譯器根據(jù) Lambda 體內(nèi)的代碼自動(dòng)推斷需要捕獲哪些變量。

  • [=]:以值捕獲的方式捕獲所有使用到的外部變量。
  • [&]:以引用捕獲的方式捕獲所有使用到的外部變量。
int a = 1, b = 2, c = 3;
// 隱式值捕獲:自動(dòng)捕獲所有使用到的外部變量 (a, b)
auto lambda1 = [=]() { std::cout << a + b << std::endl; }; 
// 注意:c 沒(méi)有被使用,所以不會(huì)被捕獲
// 隱式引用捕獲:自動(dòng)捕獲所有使用到的外部變量 (a, c)
auto lambda2 = [&]() { std::cout << a + c << std::endl; c = 100; }; 

注意:應(yīng)謹(jǐn)慎使用隱式捕獲,尤其是 [&],因?yàn)樗赡茏屇銦o(wú)意中修改外部變量或引入懸空引用。

2.4 混合捕獲

int a = 1, b = 2, c = 3, d = 4;
// a 顯式值捕獲,b 顯式引用捕獲,其他使用到的變量按值捕獲(但這里沒(méi)有其他變量了)
auto lambda1 = [=, &b]() { /* a by value, b by ref */ };
// a 顯式引用捕獲,b 顯式值捕獲,其他使用到的變量按引用捕獲(但這里沒(méi)有其他變量了)
auto lambda2 = [&, b]() { /* a by ref, b by value */ };
// 錯(cuò)誤!不能混合相同的捕獲模式: [=, a] 或 [&, &b]

2.5 捕獲 this 指針

在類的成員函數(shù)中,Lambda 可以通過(guò)值 [this] 或引用 [&] 捕獲 this 指針,從而訪問(wèn)類的成員變量和函數(shù)。

class MyClass {
public:
    void doSomething() {
        // 捕獲 this,從而可以訪問(wèn)成員變量 value
        auto lambda = [this]() { 
            std::cout << "Value: " << value << std::endl; 
            memberFunction(); 
        };
        lambda();
    }
private:
    int value = 42;
    void memberFunction() { std::cout << "Member func called\n"; }
};

2.6 初始化捕獲(C++14)

允許在捕獲時(shí)初始化變量(類似變量聲明),解決 “移動(dòng)捕獲” 等場(chǎng)景

#include <vector>
#include <utility>  // for std::move
int main() {
    vector<int> v = {1, 2, 3};
    // 初始化捕獲:將v移動(dòng)到lambda內(nèi)部的vec(避免拷貝大容器)
    auto func = [vec = move(v)] { 
        cout << "vec size: " << vec.size() << endl; 
    };
    func();  // 輸出:vec size: 3
    // cout << v.size() << endl;  // 錯(cuò)誤:v已被移動(dòng),處于無(wú)效狀態(tài)
    return 0;
}

3、mutable 關(guān)鍵字

默認(rèn)情況下,對(duì)于值捕獲的變量,Lambda 的 operator() 是 const 的,這意味著你不能在 Lambda 體內(nèi)修改這些拷貝。
使用 mutable 關(guān)鍵字可以移除這個(gè) const 限制。

int main() {
    int count = 0;
    // 沒(méi)有 mutable: 錯(cuò)誤!不能修改值捕獲的變量。
    // auto lambda = [count]() { count++; }; 
    // 使用 mutable
    auto lambda = [count]() mutable { 
        count++; // 現(xiàn)在可以修改了
        std::cout << "Count inside lambda: " << count << std::endl;
    };
    lambda(); // 輸出: Count inside lambda: 1
    lambda(); // 輸出: Count inside lambda: 2
    std::cout << "Count outside: " << count << std::endl; // 輸出: Count outside: 0
    // 注意:修改的是 Lambda 內(nèi)部的副本,不影響外部變量。
    return 0;
}

重要mutable 允許你修改的是 Lambda 內(nèi)部副本的值,對(duì)外部變量毫無(wú)影響。引用捕獲不需要 mutable。

4、返回類型

編譯器通??梢宰詣?dòng)推導(dǎo) Lambda 的返回類型。但如果函數(shù)體中有多個(gè)返回語(yǔ)句且類型不同,或者你想要更明確的代碼,可以顯式指定。

std::vector<int> numbers = {1, 2, 3, 4, 5};
// 編譯器自動(dòng)推導(dǎo)返回類型為 bool
auto is_even = [](int n) { return n % 2 == 0; };
// 顯式指定返回類型為 double (使用尾置返回類型語(yǔ)法)
auto divide = [](int a, int b) -> double {
    if (b == 0) {
        return 0.0; // 返回 double
    }
    return static_cast<double>(a) / b; // 返回 double
};

5、常見用法與示例

5.1 與 STL 算法結(jié)合

std::vector<int> vec = {5, 3, 8, 1, 9};
// 計(jì)算大于 5 的元素?cái)?shù)量
int count = std::count_if(vec.begin(), vec.end(), 
                         [](int n) { return n > 5; });
// 將所有元素翻倍
std::for_each(vec.begin(), vec.end(), 
             [](int& n) { n *= 2; }); // 注意:需要引用才能修改原值
vector<int> nums = {3, 1, 4, 1, 5, 9};
// 用lambda作為sort的比較函數(shù)(降序排序)
sort(nums.begin(), nums.end(), [](int a, int b) { 
    return a > b; 
});  // nums變?yōu)椋?,5,4,3,1,1
// 用lambda作為find_if的條件(查找偶數(shù))
auto it = find_if(nums.begin(), nums.end(), [](int x) { 
    return x % 2 == 0; 
});
if (it != nums.end()) {
    cout << "找到偶數(shù):" << *it << endl;  // 輸出:4
}

5.2 并發(fā)編程中的任務(wù)

線程或異步任務(wù)(std::thread、std::async)需要執(zhí)行函數(shù),lambda 可直接定義任務(wù)邏輯

#include <thread>
#include <future>
int main() {
    // 線程任務(wù)用lambda定義
    thread t([] { 
        cout << "線程執(zhí)行中..." << endl; 
    });
    t.join();
    // 異步任務(wù)用lambda定義
    future<int> fut = async([] { 
        return 1 + 2; 
    });
    cout << "異步結(jié)果:" << fut.get() << endl;  // 輸出:3
    return 0;
}

5.3 自定義比較器

std::map<std::string, int> name_age;
// 按值(年齡)排序,而不是鍵(名字)
std::vector<std::pair<std::string, int>> vec(name_age.begin(), name_age.end());
std::sort(vec.begin(), vec.end(),
         [](const auto& a, const auto& b) { return a.second < b.second; });

6、常見問(wèn)題

1. Lambda 表達(dá)式中的捕獲列表 [=] 和 [&] 有什么區(qū)別?[=] 表示隱式值捕獲,Lambda 體內(nèi)使用的所有外部變量都會(huì)將其當(dāng)前值拷貝一份到 Lambda 對(duì)象中。[&] 表示隱式引用捕獲,Lambda 體內(nèi)使用的所有外部變量都會(huì)以其引用被捕獲,在 Lambda 內(nèi)部修改它們會(huì)影響外部變量。應(yīng)謹(jǐn)慎使用 [&],以免造成意外的副作用或懸空引用。

2. 什么是“初始化捕獲”(Init Capture)?它解決什么問(wèn)題?初始化捕獲(C++14)允許在捕獲列表中直接初始化一個(gè)新的成員變量。它主要解決了移動(dòng)捕獲的問(wèn)題。例如,你不能用普通捕獲移動(dòng)一個(gè) std::unique_ptr(因?yàn)闊o(wú)法拷貝),但可以用 [p = std::move(unique_ptr)] 將其所有權(quán)移動(dòng)到 Lambda 內(nèi)部。它也允許你以任意表達(dá)式初始化捕獲的變量。

3. mutable 關(guān)鍵字在 Lambda 中起什么作用?默認(rèn)情況下,對(duì)于值捕獲的變量,Lambda 的函數(shù)調(diào)用運(yùn)算符 (operator()) 是 const 的,這意味著你不能修改這些捕獲的副本。mutable 關(guān)鍵字移除了這個(gè) const 限制,允許你修改 Lambda 內(nèi)部的值捕獲變量。需要注意的是,這修改的只是副本,不影響外部原始變量。

4. Lambda 表達(dá)式的類型是什么?如何存儲(chǔ)或傳遞一個(gè) Lambda?每個(gè) Lambda 表達(dá)式都會(huì)生成一個(gè)唯一的、編譯器生成的、未命名的類型(閉包類型)。存儲(chǔ)和傳遞它的最佳方式是:

  • 使用 auto 進(jìn)行初始化(auto lambda = [...](){...};)。
  • 使用 std::function(如 std::function<void()>),這會(huì)帶來(lái)一些類型擦除的開銷,但非常靈活。
  • 在模板中使用(template<typename F> void foo(F func)),這是零開銷的方式。

5. 在類的成員函數(shù)中,Lambda 如何訪問(wèn)類的成員變量?需要通過(guò)捕獲 this 指針。使用 [this] 或 [&](隱式捕獲)可以捕獲當(dāng)前對(duì)象的 this 指針,從而在 Lambda 內(nèi)部訪問(wèn)類的成員變量和成員函數(shù)。需要注意的是,如果 Lambda 的生命周期可能比對(duì)象更長(zhǎng)(例如,被放入一個(gè)全局隊(duì)列),這會(huì)導(dǎo)致懸空 this 指針。C++17 的 [\*this] 可以按值捕獲整個(gè)對(duì)象的副本,避免這個(gè)問(wèn)題。

到此這篇關(guān)于C++ lambda 匿名函數(shù)深入解析的文章就介紹到這了,更多相關(guān)C++ lambda 匿名函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Linux下動(dòng)靜態(tài)庫(kù)的打包與使用指南(C/C++)

    Linux下動(dòng)靜態(tài)庫(kù)的打包與使用指南(C/C++)

    c++是面向?qū)ο蟮木幊陶Z(yǔ)言,比較方便實(shí)現(xiàn)某些第三方庫(kù),比如翻譯其他面向?qū)ο笳Z(yǔ)言的代碼,比c語(yǔ)言要方便的多,下面這篇文章主要給大家介紹了關(guān)于Linux下C/C++動(dòng)靜態(tài)庫(kù)的打包與使用的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • C++運(yùn)算符重載圖文詳解

    C++運(yùn)算符重載圖文詳解

    運(yùn)算符重載的方法是定義一個(gè)重載運(yùn)算符的函數(shù),在需要執(zhí)行被重載的運(yùn)算符時(shí),系統(tǒng)就自動(dòng)調(diào)用該函數(shù),以實(shí)現(xiàn)相應(yīng)的運(yùn)算。也就是說(shuō),運(yùn)算符重載是通過(guò)定義函數(shù)實(shí)現(xiàn)的
    2021-09-09
  • C++數(shù)據(jù)結(jié)構(gòu)之哈希算法詳解

    C++數(shù)據(jù)結(jié)構(gòu)之哈希算法詳解

    這篇文章主要為大家詳細(xì)介紹了C++數(shù)據(jù)結(jié)構(gòu)中哈希算法的相關(guān)資料,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,希望對(duì)大家有所幫助
    2022-12-12
  • C語(yǔ)言結(jié)構(gòu)體使用之鏈表

    C語(yǔ)言結(jié)構(gòu)體使用之鏈表

    這篇文章主要介紹了C語(yǔ)言結(jié)構(gòu)體使用之鏈表,下面文章主要圍繞結(jié)構(gòu)體的概念和用法、結(jié)構(gòu)體數(shù)組和結(jié)構(gòu)體指針、包含結(jié)構(gòu)體的結(jié)構(gòu)體、結(jié)構(gòu)體搭建鏈表方法、結(jié)構(gòu)體及鏈表在產(chǎn)品應(yīng)用場(chǎng)景等多個(gè)主題展開鏈表的相關(guān)資料,需要的小伙伴可以參考一下
    2022-03-03
  • C++ 自增、自減運(yùn)算符的重載和性能分析小結(jié)

    C++ 自增、自減運(yùn)算符的重載和性能分析小結(jié)

    這篇文章主要介紹了C++ 自增、自減運(yùn)算符的重載和性能分析小結(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • 詳解c語(yǔ)言中的 strcpy和strncpy字符串函數(shù)使用

    詳解c語(yǔ)言中的 strcpy和strncpy字符串函數(shù)使用

    strcpy 和strcnpy函數(shù)是字符串復(fù)制函數(shù)。接下來(lái)通過(guò)本文給大家介紹c語(yǔ)言中的strcpy和strncpy字符串函數(shù)使用,感興趣的朋友跟隨小編要求看看吧
    2018-10-10
  • VS未找到框架“.NETFramework,Version=v4.6.1”引用程序集的解決辦法

    VS未找到框架“.NETFramework,Version=v4.6.1”引用程序集的解決辦法

    本文主要介紹了VS未找到框架“.NETFramework,Version=v4.6.1”引用程序集的解決辦法,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-10-10
  • C語(yǔ)言詳解格式控制符scanf與printf的輸入輸出

    C語(yǔ)言詳解格式控制符scanf與printf的輸入輸出

    這篇文章主要介紹了C語(yǔ)言格式控制符中輸入scanf()和輸出printf()的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2022-04-04
  • windows?使用ffmpeg?.a靜態(tài)庫(kù)讀取Wav音頻并保存PCM的方法

    windows?使用ffmpeg?.a靜態(tài)庫(kù)讀取Wav音頻并保存PCM的方法

    這篇文章主要介紹了windows?使用ffmpeg?.a靜態(tài)庫(kù)讀取Wav音頻并保存PCM,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2024-02-02
  • VisualStudio2022提交git代碼的方法實(shí)現(xiàn)

    VisualStudio2022提交git代碼的方法實(shí)現(xiàn)

    本文主要介紹了VisualStudio2022提交git代碼的方法實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07

最新評(píng)論

札达县| 贵南县| 肥城市| 东丽区| 章丘市| 肇庆市| 顺平县| 北票市| 宜丰县| 武汉市| 赞皇县| 宁海县| 达州市| 河津市| 湘潭县| 临泽县| 南靖县| 乃东县| 冀州市| 万载县| 柘城县| 宝丰县| 沙坪坝区| 南川市| 烟台市| 临清市| 榆社县| 合阳县| 高安市| 庆阳市| 开化县| 东平县| 凉城县| 英德市| 苏州市| 沙坪坝区| 肇东市| 连平县| 花莲市| 华安县| 余庆县|