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

C++11?lambda(匿名函數(shù))表達(dá)式詳細(xì)介紹

 更新時(shí)間:2022年07月11日 10:57:50   作者:luoyayun361  
lambda 表達(dá)式(lambda expression)是一個(gè)匿名函數(shù),C++11中的lambda表達(dá)式用于定義并創(chuàng)建匿名的函數(shù)對(duì)象,以簡(jiǎn)化編程工作,下面這篇文章主要給大家介紹了關(guān)于C++11?lambda(匿名函數(shù))表達(dá)式的相關(guān)資料,需要的朋友可以參考下

前言

Lambda(匿名函數(shù))表達(dá)式是C++11最重要的特性之一,lambda來源于函數(shù)式編程的概念,也是現(xiàn)代編程語言的一個(gè)特點(diǎn)。

優(yōu)點(diǎn)如下:

  • 聲明式編程風(fēng)格:就地匿名定義目標(biāo)函數(shù)或函數(shù)對(duì)象,有更好的可讀性和可維護(hù)性。
  • 簡(jiǎn)潔:不需要額外寫一個(gè)命名函數(shù)或函數(shù)對(duì)象,,避免了代碼膨脹和功能分散。
  • 更加靈活:在需要的時(shí)間和地點(diǎn)實(shí)現(xiàn)功能閉包。

概念及基本用法

lambda表達(dá)式定義了一個(gè)匿名函數(shù),并且可以捕獲一定范圍內(nèi)的變量。語法形式如下:

[ capture ] ( params ) opt -> ret { body; };

  • capture:捕獲列表
  • params:參數(shù)列表
  • opt:函數(shù)選項(xiàng)
  • ret:返回值類型
  • body:函數(shù)體

一個(gè)完整的lambda表達(dá)式是這樣:

auto f = [](int a) -> int {return a + 1;};
cout << f(3) << endl;  //輸出4

以上定義了一個(gè)完整的lambda,但是在實(shí)際的使用中,可以省略其返回值的定義,編譯器會(huì)根據(jù)return語句進(jìn)行自動(dòng)推導(dǎo)返回值類型。

省略過后如下:

auto f = [](int a) {return a + 1;};

需要注意的是,初始化列表不能用于返回值的自動(dòng)推導(dǎo):

如:auto f = [](){return {1,2};}; //error:無法推導(dǎo)返回值類型

另外,如果表達(dá)式?jīng)]有參數(shù)列表時(shí),也可以省略,如:

auto f = []{return 1;};

捕獲變量

lambda表達(dá)式可以通過捕獲列表捕獲一定范圍內(nèi)的變量,主要有以下幾種情況:

  • [] 不捕獲任何變量
  • [&]捕獲外部作用域中所有變量,并作為引用在函數(shù)體中使用(按引用捕獲)
  • [=]捕獲外部作用域中所有變量,并作為副本在函數(shù)體重使用(按值捕獲)
  • [=,&foo] 按值捕獲外部作用域中所有變量,并按引用捕獲foo變量
  • [bar] 按值捕獲bar變量,同時(shí)不捕獲其他變量
  • [this] 捕獲當(dāng)前類中的this指針,讓表達(dá)式擁有和當(dāng)前類成員函數(shù)同樣的訪問權(quán)限。如果已經(jīng)使用了&或者=,就默認(rèn)添加此選項(xiàng)。捕獲this的目的是可以在lambda中使用當(dāng)前類的成員變量和成員函數(shù)。

通過示例來看具體用法:

class A 
{
public:
    int i_ = 0;
    
    void func(int x,int y)
    {
        auto x1 = []{return i_;};  // error,沒有捕獲外部變量
        auto x2 = [=]{return i_ + x + y;}; //ok,按值捕獲所有外部變量
        auto x3 = [&]{return i_ + x + y;}; //ok,按引用捕獲所有外部變量
        auto x4 = [this]{return i_;}; //ok,捕獲this指針
        auto x5 = [this]{return i_ + x + y;}; //error,沒有捕獲x和y變量
        auto x6 = [this,x,y]{return i_ + x + y;}; //ok,捕獲了this指針和x、y變量
        auto x7 = [this]{return i_++;}; //ok,捕獲了this指針,修改成員變量的值
    }
};
int a = 0 , b = 0 ;
auto f1 = []{return a;}; // error,沒有捕獲外部變量
auto f2 = [&]{return a++;}; //ok,捕獲所有外部變量,并對(duì)a變量自加
auto f3 = [=]{return a;}; //ok,捕獲所有外部變量,并返回a
auto f4 = [=]{return a++;}; //error,a變量是以復(fù)制方式捕獲的,不能修改
auto f5 = [a]{return a+b;}; //error,沒有捕獲b變量
auto f6 = [a,&b]{return a+ (b++);}; //ok,捕獲a以及b的引用,對(duì)b進(jìn)行自加
auto f7 = [=,&b]{return a+ (b++);}; //ok, 捕獲所有外部變量和b的引用,對(duì)b進(jìn)行自加

需要注意的是,lambda無法修改按值捕獲的外部變量,如果需要修改外部變量,可以通過引用方式捕獲。

關(guān)于lambda表達(dá)式的延遲調(diào)用很容易出錯(cuò),如下:

int a = 0;
auto f = [=]{return a;};
a += 1;
cout << f() << endl;

以上示例中,lambda按值捕獲了所有外部變量,在捕獲的時(shí)候 a的值就已經(jīng)被復(fù)制到 f 中了,之后a被修改,但是f里面存儲(chǔ)的a仍然是捕獲時(shí)的值,所以最終輸出的是 0.

如果希望lambda表達(dá)式在調(diào)用的時(shí)候能夠訪問外部變量,需要使用引用方式捕獲。

所以簡(jiǎn)單來說,按值捕獲,外部變量會(huì)被復(fù)制一份存儲(chǔ)在lambda表達(dá)式變量中。

如果是按值捕獲并且又想修改外部變量,可以顯示指明lambda表達(dá)式為mutable:

int a = 0;
auto f1 = [=]{return a++;};  //error,修改按值捕獲的外部變量
auto f2 = [=]() mutable {return a++;}; //ok

被mutable修飾的lambda表達(dá)式就算沒有參數(shù)也要寫明參數(shù)列表。

lambda表達(dá)式類型

lambda表達(dá)式的類型在C++11中被稱為“閉包類型”,它是一個(gè)特殊的,匿名的非nunion的類型。

可以認(rèn)為它是帶有一個(gè)operator()的類,即仿函數(shù)。
我們可以通過std::function和std::bind來存儲(chǔ)和操作lambda表達(dá)式:

std::function<int(int)> f1 = [](int a){return a;};
std::function<int(void)> f2 = std::bind([](int a){return a;},123);

另外,對(duì)于沒有捕獲任何變量的lambda表達(dá)式,還可以被轉(zhuǎn)換成一個(gè)普通的函數(shù)指針:

using func_t = int(*)(int);
func_t f = [](int a){return a;};
f(123);

lambda可以說是就地定義仿函數(shù)閉包的“語法 糖”。它的捕獲列表捕獲住任何外部變量,最終都會(huì)變?yōu)殚]包類型的成員變量。而一個(gè)成員變量的類的operator(),如果能直接被轉(zhuǎn)換為普通的函數(shù)指針,那么lambda表達(dá)式本身的this指針就丟掉了。而沒有捕獲任何外部變量的lambda表達(dá)式則不存在這個(gè)問題。

需要注意的是,沒有捕獲變量的lambda表達(dá)式可以直接轉(zhuǎn)換為函數(shù)指針,而捕獲變量的lambda表達(dá)式則不能轉(zhuǎn)換為函數(shù)指針。如下:

typedef void(*Ptr)(int*);
Ptr p = [](int *p){delete p;};  //ok
Ptr p1 = [&](int *p){delete p;}; //error

前面說到的按值捕獲無法修改捕獲的外部變量,因?yàn)榘凑誄++標(biāo)準(zhǔn),lambda表達(dá)式的operator()默認(rèn)是const的,一個(gè)const成員函數(shù)是無法修改成員變量的值,而mutable的作用,就是取消operator()的const限制。

聲明式的編程風(fēng)格

通過示例來看一下lambda的使用,在C++11之前,如果要用for_each函數(shù)將數(shù)組中的偶數(shù)數(shù)量打印出來,代碼如下:

#include <vector>
#include <algorithm>
class Count
{
public:
? ? Count(int &val):num(val){}
? ? void operator()(int val){
? ? ? ? if(!(val & 1)){
? ? ? ? ? ? ++num;
? ? ? ? }
? ? }
private:
? ? int &num;
};

int main()
{
? ? std::vector<int> v = {1,2,3,4,5,6,7};
? ? int count = 0;
? ? for_each(v.begin(),v.end(),Count(count));
? ? std::cout << count << endl;
? ? return 0;
}

如果使用lambda表達(dá)式,就可以簡(jiǎn)化一下,真正使用閉包概念來替換這里的仿函數(shù)。

#include <vector>
#include <algorithm>

int main()
{
    std::vector<int> v = {1,2,3,4,5,6,7};
    int count = 0;
    for_each(v.begin(),v.end(),[&count](int val){
        if(!(val & 1)){
            ++count;
        }
    });

    std::cout << count << endl;
    return 0;
}

lambda表達(dá)式的價(jià)值在于,就地封裝短小的功能閉包,方便地表達(dá)出我們希望執(zhí)行的具體操作,并讓上下文結(jié)合的更加緊,代碼更加簡(jiǎn)潔,更靈活,也提高了開發(fā)效率及可維護(hù)性。

參考:《深入應(yīng)用C++11》

總結(jié)

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

相關(guān)文章

  • C語言深入探究冒泡排序與堆排序使用案例講解

    C語言深入探究冒泡排序與堆排序使用案例講解

    算法中排序是十分重要的,而每一個(gè)學(xué)習(xí)計(jì)算機(jī)的都會(huì)在初期的時(shí)候接觸到這種排序,下面這篇文章主要給大家介紹了關(guān)于c語言冒泡排序與堆排序使用的相關(guān)資料,需要的朋友可以參考下
    2022-05-05
  • C++計(jì)算每個(gè)字符出現(xiàn)的次數(shù)

    C++計(jì)算每個(gè)字符出現(xiàn)的次數(shù)

    這篇文章主要介紹了C++計(jì)算每個(gè)字符出現(xiàn)的次數(shù)的相關(guān)資料,需要的朋友可以參考下
    2016-05-05
  • C語言中單鏈表(不帶頭結(jié)點(diǎn))基本操作的實(shí)現(xiàn)詳解

    C語言中單鏈表(不帶頭結(jié)點(diǎn))基本操作的實(shí)現(xiàn)詳解

    鏈表是一種物理存儲(chǔ)結(jié)構(gòu)上非連續(xù)、非順序的存儲(chǔ)結(jié)構(gòu),數(shù)據(jù)元素的邏輯順序是通過鏈表中的指針鏈接次序?qū)崿F(xiàn)的。本文主要和大家聊聊C語言中單鏈表(不帶頭結(jié)點(diǎn))的基本操作,感興趣的小伙伴可以了解一下
    2022-11-11
  • C語言實(shí)現(xiàn)手寫字符串處理工具的示例代碼

    C語言實(shí)現(xiàn)手寫字符串處理工具的示例代碼

    這篇文章主要為大家詳細(xì)介紹了利用C語言實(shí)現(xiàn)手寫字符串處理工具的相關(guān)資料,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的可以參考一下
    2022-09-09
  • 基于C語言實(shí)現(xiàn)的TCP服務(wù)器的流程分析

    基于C語言實(shí)現(xiàn)的TCP服務(wù)器的流程分析

    本文詳細(xì)介紹了如何使用C語言編寫一個(gè)簡(jiǎn)單的TCP服務(wù)器,包括創(chuàng)建套接字、綁定IP和端口、監(jiān)聽連接請(qǐng)求、接受客戶端連接、數(shù)據(jù)接收與發(fā)送以及關(guān)閉套接字等步驟,最后通過一個(gè)簡(jiǎn)單的示例展示了TCP服務(wù)器的基本實(shí)現(xiàn)過程
    2024-10-10
  • C語言 數(shù)據(jù)結(jié)構(gòu)之?dāng)?shù)組模擬實(shí)現(xiàn)順序表流程詳解

    C語言 數(shù)據(jù)結(jié)構(gòu)之?dāng)?shù)組模擬實(shí)現(xiàn)順序表流程詳解

    順序表,全名順序存儲(chǔ)結(jié)構(gòu),是線性表的一種,線性表用于存儲(chǔ)邏輯關(guān)系為“一對(duì)一”的數(shù)據(jù),順序表自然也不例外,不僅如此,順序表對(duì)數(shù)據(jù)的物理存儲(chǔ)結(jié)構(gòu)也有要求,跟隨下文來具體了解吧
    2021-11-11
  • 簡(jiǎn)單談?wù)凜語言中的= 和==、!=

    簡(jiǎn)單談?wù)凜語言中的= 和==、!=

    這篇文章主要給大家介紹了關(guān)于C語言中= 和==、!=的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • c++初級(jí)并查集知識(shí)點(diǎn)總結(jié)

    c++初級(jí)并查集知識(shí)點(diǎn)總結(jié)

    在本篇文章里小編給各位分享的是關(guān)于c++初級(jí)并查集知識(shí)點(diǎn)以及實(shí)例代碼內(nèi)容,有需要的朋友們學(xué)習(xí)下。
    2019-07-07
  • C語言線性代數(shù)算法實(shí)現(xiàn)矩陣示例代碼

    C語言線性代數(shù)算法實(shí)現(xiàn)矩陣示例代碼

    這篇文章主要為大家介紹了使用C語言線性代數(shù)的算法來實(shí)現(xiàn)矩陣示例代碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2021-10-10
  • C++中volatile關(guān)鍵字及常見的誤解總結(jié)

    C++中volatile關(guān)鍵字及常見的誤解總結(jié)

    這篇文章主要給大家介紹了關(guān)于C++中volatile關(guān)鍵字及常見的誤解的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-05-05

最新評(píng)論

什邡市| 林州市| 屯昌县| 香港 | 浮山县| 巩义市| 上蔡县| 中西区| 寻乌县| 北宁市| 汉寿县| 垫江县| 日土县| 若尔盖县| 曲麻莱县| 南乐县| 邯郸市| 阜康市| 高阳县| 威海市| 黑山县| 博客| 隆子县| 越西县| 堆龙德庆县| 四川省| 乐平市| 泰州市| 武强县| 瓦房店市| 晴隆县| 甘南县| 韩城市| 鹤峰县| 兴文县| 赤城县| 上杭县| 饶平县| 无锡市| 黔南| 凤阳县|