欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++ lambda函數(shù)詳解

 更新時間:2023年02月13日 15:49:31   作者:scott198512  
小編可以明確告訴大家:lambda函數(shù)是C++11中最重要的,使用最廣泛的,最具現(xiàn)代風(fēng)格的內(nèi)容,lambda函數(shù)的出現(xiàn)改變了C++編程的思維方式。所以快和小編學(xué)習(xí)一下C++11中l(wèi)ambda函數(shù)的使用吧

Lambda 表達式

Lambda 表達式是現(xiàn)代 C++ 中最重要的特性之一,而 Lambda 表達式,實際上就是提供了一個類似匿名函數(shù)的特性, 而匿名函數(shù)則是在需要一個函數(shù),但是又不想費力去命名一個函數(shù)的情況下去使用的。這樣的場景其實有很多很多, 所以匿名函數(shù)幾乎是現(xiàn)代編程語言的標(biāo)配。

基礎(chǔ)

Lambda 表達式的基本語法如下:

[捕獲列表](參數(shù)列表) mutable(可選) 異常屬性 -> 返回類型 {
// 函數(shù)體
}

上面的語法規(guī)則除了 [捕獲列表] 內(nèi)的東西外,其他部分都很好理解,只是一般函數(shù)的函數(shù)名被略去, 返回值使用了一個 -> 的形式進行(我們在上一節(jié)前面的尾返回類型已經(jīng)提到過這種寫法了)。

所謂捕獲列表,其實可以理解為參數(shù)的一種類型,Lambda 表達式內(nèi)部函數(shù)體在默認(rèn)情況下是不能夠使用函數(shù)體外部的變量的, 這時候捕獲列表可以起到傳遞外部數(shù)據(jù)的作用。根據(jù)傳遞的行為,捕獲列表也分為以下幾種:

1. 值捕獲

與參數(shù)傳值類似,值捕獲的前提是變量可以拷貝,不同之處則在于,被捕獲的變量在 Lambda 表達式被創(chuàng)建時拷貝, 而非調(diào)用時才拷貝:

void lambda_value_capture() {
    int value = 1;
    auto copy_value = [value] {
        return value;
    };
    value = 100;
    auto stored_value = copy_value();
    std::cout << "stored_value = " << stored_value << std::endl;
    // 這時, stored_value == 1, 而 value == 100.
    // 因為 copy_value 在創(chuàng)建時就保存了一份 value 的拷貝
}

2. 引用捕獲

與引用傳參類似,引用捕獲保存的是引用,值會發(fā)生變化。

void lambda_reference_capture() {
    int value = 1;
    auto copy_value = [&value] {
        return value;
    };
    value = 100;
    auto stored_value = copy_value();
    std::cout << "stored_value = " << stored_value << std::endl;
    // 這時, stored_value == 100, value == 100.
    // 因為 copy_value 保存的是引用
}

3. 隱式捕獲

手動書寫捕獲列表有時候是非常復(fù)雜的,這種機械性的工作可以交給編譯器來處理,這時候可以在捕獲列表中寫一個 & 或 = 向編譯器聲明采用引用捕獲或者值捕獲.

總結(jié)一下,捕獲提供了 Lambda 表達式對外部值進行使用的功能,捕獲列表的最常用的四種形式可以是:

a. [] 空捕獲列表
b. [name1, name2, ...] 捕獲一系列變量
c. [&] 引用捕獲, 讓編譯器自行推導(dǎo)引用列表
d. [=] 值捕獲, 讓編譯器自行推導(dǎo)值捕獲列表

4. 表達式捕獲

這部分內(nèi)容需要了解后面馬上要提到的右值引用以及智能指針

上面提到的值捕獲、引用捕獲都是已經(jīng)在外層作用域聲明的變量,因此這些捕獲方式捕獲的均為左值,而不能捕獲右值。

C++14 給與了我們方便,允許捕獲的成員用任意的表達式進行初始化,這就允許了右值的捕獲, 被聲明的捕獲變量類型會根據(jù)表達式進行判斷,判斷方式與使用 auto 本質(zhì)上是相同的:

#include <iostream>
#include <memory>  // std::make_unique
#include <utility> // std::move
void lambda_expression_capture() {
    auto important = std::make_unique<int>(1);
    auto add = [v1 = 1, v2 = std::move(important)](int x, int y) -> int {
        return x+y+v1+(*v2);
    };
    std::cout << add(3,4) << std::endl;
}

在上面的代碼中,important 是一個獨占指針,是不能夠被 "=" 值捕獲到,這時候我們可以將其轉(zhuǎn)移為右值,在表達式中初始化。

泛型 Lambda

上一節(jié)中我們提到了 auto 關(guān)鍵字不能夠用在參數(shù)表里,這是因為這樣的寫法會與模板的功能產(chǎn)生沖突。 但是 Lambda 表達式并不是普通函數(shù),所以在沒有明確指明參數(shù)表類型的情況下,Lambda 表達式并不能夠模板化。 幸運的是,這種麻煩只存在于 C++11 中,從 C++14 開始,Lambda 函數(shù)的形式參數(shù)可以使用 auto 關(guān)鍵字來產(chǎn)生意義上的泛型:

auto add = [](auto x, auto y) {
    return x+y;
};
add(1, 2);
add(1.1, 2.2);

函數(shù)對象包裝器

這部分內(nèi)容雖然屬于標(biāo)準(zhǔn)庫的一部分,但是從本質(zhì)上來看,它卻增強了 C++ 語言運行時的能力, 這部分內(nèi)容也相當(dāng)重要,所以放到這里來進行介紹。

std::function

Lambda 表達式的本質(zhì)是一個和函數(shù)對象類型相似的類類型(稱為閉包類型)的對象(稱為閉包對象), 當(dāng) Lambda 表達式的捕獲列表為空時,閉包對象還能夠轉(zhuǎn)換為函數(shù)指針值進行傳遞,例如:

#include <iostream>
using foo = void(int); // 定義函數(shù)類型, using 的使用見上一節(jié)中的別名語法
void functional(foo f) { // 參數(shù)列表中定義的函數(shù)類型 foo 被視為退化后的函數(shù)指針類型 foo*
    f(1); // 通過函數(shù)指針調(diào)用函數(shù)
}
int main() {
    auto f = [](int value) {
        std::cout << value << std::endl;
    };
    functional(f); // 傳遞閉包對象,隱式轉(zhuǎn)換為 foo* 類型的函數(shù)指針值
    f(1); // lambda 表達式調(diào)用
    return 0;
}

上面的代碼給出了兩種不同的調(diào)用形式,一種是將 Lambda 作為函數(shù)類型傳遞進行調(diào)用, 而另一種則是直接調(diào)用 Lambda 表達式,在 C++11 中,統(tǒng)一了這些概念,將能夠被調(diào)用的對象的類型, 統(tǒng)一稱之為可調(diào)用類型。而這種類型,便是通過 std::function 引入的。

C++11 std::function 是一種通用、多態(tài)的函數(shù)封裝, 它的實例可以對任何可以調(diào)用的目標(biāo)實體進行存儲、復(fù)制和調(diào)用操作, 它也是對 C++ 中現(xiàn)有的可調(diào)用實體的一種類型安全的包裹(相對來說,函數(shù)指針的調(diào)用不是類型安全的), 換句話說,就是函數(shù)的容器。當(dāng)我們有了函數(shù)的容器之后便能夠更加方便的將函數(shù)、函數(shù)指針作為對象進行處理。 例如:

#include <functional>
#include <iostream>
int foo(int para) {
    return para;
}
int main() {
    // std::function 包裝了一個返回值為 int, 參數(shù)為 int 的函數(shù)
    std::function<int(int)> func = foo;
    int important = 10;
    std::function<int(int)> func2 = [&](int value) -> int {
        return 1+value+important;
    };
    std::cout << func(10) << std::endl;
    std::cout << func2(10) << std::endl;
}
std::bind 和 std::placeholder

而 std::bind 則是用來綁定函數(shù)調(diào)用的參數(shù)的, 它解決的需求是我們有時候可能并不一定能夠一次性獲得調(diào)用某個函數(shù)的全部參數(shù),通過這個函數(shù), 我們可以將部分調(diào)用參數(shù)提前綁定到函數(shù)身上成為一個新的對象,然后在參數(shù)齊全后,完成調(diào)用。 例如:

int foo(int a, int b, int c) {
    ;
}
int main() {
    // 將參數(shù)1,2綁定到函數(shù) foo 上,
    // 但使用 std::placeholders::_1 來對第一個參數(shù)進行占位
    auto bindFoo = std::bind(foo, std::placeholders::_1, 1,2);
    // 這時調(diào)用 bindFoo 時,只需要提供第一個參數(shù)即可
    bindFoo(1);
}

提示:注意 auto 關(guān)鍵字的妙用。有時候我們可能不太熟悉一個函數(shù)的返回值類型, 但是我們卻可以通過 auto 的使用來規(guī)避這一問題的出現(xiàn)。

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

相關(guān)文章

  • C++簡單實現(xiàn)shared_ptr的代碼

    C++簡單實現(xiàn)shared_ptr的代碼

    智能指針用于資源管理,為了保證資源的操作得到順利的執(zhí)行防止資源泄露,因此大多數(shù)實現(xiàn)都以noexcept在參數(shù)列表后聲明為不拋出異常,這篇文章主要介紹了C++簡單實現(xiàn)shared_ptr的代碼,需要的朋友可以參考下
    2022-09-09
  • C語言自定義數(shù)據(jù)類型的結(jié)構(gòu)體、枚舉和聯(lián)合詳解

    C語言自定義數(shù)據(jù)類型的結(jié)構(gòu)體、枚舉和聯(lián)合詳解

    這篇文章主要給大家介紹了關(guān)于C語言自定義數(shù)據(jù)類型的結(jié)構(gòu)體、枚舉和聯(lián)合的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • C++ Boost Tokenizer使用詳細講解

    C++ Boost Tokenizer使用詳細講解

    Boost是為C++語言標(biāo)準(zhǔn)庫提供擴展的一些C++程序庫的總稱。Boost庫是一個可移植、提供源代碼的C++庫,作為標(biāo)準(zhǔn)庫的后備,是C++標(biāo)準(zhǔn)化進程的開發(fā)引擎之一,是為C++語言標(biāo)準(zhǔn)庫提供擴展的一些C++程序庫的總稱
    2022-11-11
  • 解析一個有關(guān)sizeof用法的題目--sizeof(i++)

    解析一個有關(guān)sizeof用法的題目--sizeof(i++)

    本篇文章是對一個關(guān)于sizeof用法的題目進行了詳細的分析介紹,需要的朋友參考下
    2013-06-06
  • C++實現(xiàn)機票預(yù)訂系統(tǒng)

    C++實現(xiàn)機票預(yù)訂系統(tǒng)

    這篇文章主要為大家詳細介紹了C++實現(xiàn)機票預(yù)訂系統(tǒng),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • 深度理解C語言中的關(guān)鍵字static

    深度理解C語言中的關(guān)鍵字static

    在C語言中static主要定義全局靜態(tài)變量、定義局部靜態(tài)變量、定義靜態(tài)函數(shù),下面這篇文章主要給大家介紹了關(guān)于C語言中關(guān)鍵字static的相關(guān)資料,需要的朋友可以參考下
    2021-08-08
  • C語言編寫漢諾塔游戲

    C語言編寫漢諾塔游戲

    這篇文章主要介紹了C語言編寫漢諾塔游戲,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2021-11-11
  • 千萬不要被階乘嚇倒

    千萬不要被階乘嚇倒

    本篇文章是對階乘進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05
  • C/C++實現(xiàn)線性單鏈表的示例代碼

    C/C++實現(xiàn)線性單鏈表的示例代碼

    使用鏈存儲結(jié)構(gòu)的線性存儲結(jié)構(gòu)為線性單鏈表,本文將分別利用C語言和C++實現(xiàn)線性單鏈表,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2022-05-05
  • C++學(xué)習(xí)之虛函數(shù)表與多態(tài)詳解

    C++學(xué)習(xí)之虛函數(shù)表與多態(tài)詳解

    這篇文章主要為大家詳細介紹了C++中虛函數(shù)表與多態(tài)的相關(guān)知識,文中的示例代碼講解詳細,對我們學(xué)習(xí)C++有一定的幫助,感興趣的小伙伴可以了解一下
    2023-03-03

最新評論