亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

C++中的Lambda表達式詳解

2020-01-26 15:14:38
字體:
來源:轉載
供稿:網友

我是搞C++的

一直都在提醒自己,我是搞C++的;但是當C++11出來這么長時間了,我卻沒有跟著隊伍走,發現很對不起自己的身份,也還好,發現自己也有段時間沒有寫C++代碼了。今天看到了C++中的Lambda表達式,雖然用過C#的,但是C++的,一直沒有用,也不知道怎么用,就可憐的連Lambda語法都看不懂。好了,這里就對C++中的Lambda進行一個簡單的總結,就算是對自己的一個交代,我是搞C++的,我是一個C++ programmer。

一段簡單的Code

我也不是文藝的人,對于Lambda的歷史,以及Lambda與C++的那段淵源,我也不是很熟悉,技術人,講究拿代碼說事。

復制代碼 代碼如下:

#include<iostream>
using namespace std;
 
int main()
{
    int a = 1;
    int b = 2;
 
    auto func = [=, &b](int c)->int {return b += a + c;};
    return 0;
}

當我第一次看到這段代碼時,我直接凌亂了,直接看不懂啊。上面這段代碼,如果你看懂了,下面的內容就當時復習了;如果看不懂了,就接著和我一起總結吧。

基本語法

簡單來說,Lambda函數也就是一個函數,它的語法定義如下:

復制代碼 代碼如下:

[capture](parameters) mutable ->return-type{statement}

1.[capture]:捕捉列表。捕捉列表總是出現在Lambda函數的開始處。實際上,[]是Lambda引出符。編譯器根據該引出符判斷接下來的代碼是否是Lambda函數。捕捉列表能夠捕捉上下文中的變量以供Lambda函數使用;

2.(parameters):參數列表。與普通函數的參數列表一致。如果不需要參數傳遞,則可以連同括號“()”一起省略;

3.mutable:mutable修飾符。默認情況下,Lambda函數總是一個const函數,mutable可以取消其常量性。在使用該修飾符時,參數列表不可省略(即使參數為空);

4.->return-type:返回類型。用追蹤返回類型形式聲明函數的返回類型。我們可以在不需要返回值的時候也可以連同符號”->”一起省略。此外,在返回類型明確的情況下,也可以省略該部分,讓編譯器對返回類型進行推導;

5.{statement}:函數體。內容與普通函數一樣,不過除了可以使用參數之外,還可以使用所有捕獲的變量。

與普通函數最大的區別是,除了可以使用參數以外,Lambda函數還可以通過捕獲列表訪問一些上下文中的數據。具體地,捕捉列表描述了上下文中哪些數據可以被Lambda使用,以及使用方式(以值傳遞的方式或引用傳遞的方式)。語法上,在“[]”包括起來的是捕捉列表,捕捉列表由多個捕捉項組成,并以逗號分隔。捕捉列表有以下幾種形式:

1.[var]表示值傳遞方式捕捉變量var;
2.[=]表示值傳遞方式捕捉所有父作用域的變量(包括this);
3.[&var]表示引用傳遞捕捉變量var;
4.[&]表示引用傳遞方式捕捉所有父作用域的變量(包括this);
5.[this]表示值傳遞方式捕捉當前的this指針。

上面提到了一個父作用域,也就是包含Lambda函數的語句塊,說通俗點就是包含Lambda的“{}”代碼塊。上面的捕捉列表還可以進行組合,例如:

1.[=,&a,&b]表示以引用傳遞的方式捕捉變量a和b,以值傳遞方式捕捉其它所有變量;
2.[&,a,this]表示以值傳遞的方式捕捉變量a和this,引用傳遞方式捕捉其它所有變量。

不過值得注意的是,捕捉列表不允許變量重復傳遞。下面一些例子就是典型的重復,會導致編譯時期的錯誤。例如:

3.[=,a]這里已經以值傳遞方式捕捉了所有變量,但是重復捕捉a了,會報錯的;
4.[&,&this]這里&已經以引用傳遞方式捕捉了所有變量,再捕捉this也是一種重復。

Lambda的使用

對于Lambda的使用,說實話,我沒有什么多說的,個人理解,在沒有Lambda之前的C++ , 我們也是那樣好好的使用,并沒有對缺少Lambda的C++有什么抱怨,而現在有了Lambda表達式,只是更多的方便了我們去寫代碼。不知道大家是否記得C++ STL庫中的仿函數對象,仿函數想對于普通函數來說,仿函數可以擁有初始化狀態,而這些初始化狀態是在聲明仿函數對象時,通過參數指定的,一般都是保存在仿函數對象的私有變量中;在C++中,對于要求具有狀態的函數,我們一般都是使用仿函數來實現,比如以下代碼:

復制代碼 代碼如下:

#include<iostream>
using namespace std;
 
typedef enum
{
    add = 0,
    sub,
    mul,
    divi
}type;
 
class Calc
{
    public:
        Calc(int x, int y):m_x(x), m_y(y){}
 
        int operator()(type i)
        {
            switch (i)
            {
                case add:
                    return m_x + m_y;
                case sub:
                    return m_x - m_y;
                case mul:
                    return m_x * m_y;
                case divi:
                    return m_x / m_y;
            }
        }
 
    private:
        int m_x;
        int m_y;
};
 
int main()
{
    Calc addObj(10, 20);
    cout<<addObj(add)<<endl; // 發現C++11中,enum類型的使用也變了,更“強”了                                                                                                                                             
    return 0;
}

現在我們有了Lambda這個利器,那是不是可以重寫上面的實現呢?看代碼:

復制代碼 代碼如下:

#include<iostream>
using namespace std;
     
typedef enum
{    
    add = 0,
    sub,
    mul,
    divi
}type;
     
int main()
{    
    int a = 10;
    int b = 20;
     
    auto func = [=](type i)->int {
        switch (i)
        {
            case add:
                return a + b;
            case sub:
                return a - b;
            case mul:
                return a * b;
            case divi:
                return a / b;
        }
    };
     
    cout<<func(add)<<endl;
}

顯而易見的效果,代碼簡單了,你也少寫了一些代碼,也去試一試C++中的Lambda表達式吧。

關于Lambda那些奇葩的東西

看以下一段代碼:

復制代碼 代碼如下:

#include<iostream>        
using namespace std;      
                          
int main()                
{                         
    int j = 10;           
    auto by_val_lambda = [=]{ return j + 1; };
    auto by_ref_lambda = [&]{ return j + 1; };
    cout<<"by_val_lambda: "<<by_val_lambda()<<endl;
    cout<<"by_ref_lambda: "<<by_ref_lambda()<<endl;
                          
    ++j;                  
    cout<<"by_val_lambda: "<<by_val_lambda()<<endl;
    cout<<"by_ref_lambda: "<<by_ref_lambda()<<endl;
                          
    return 0;             
}

程序輸出結果如下:

復制代碼 代碼如下:

by_val_lambda: 11
by_ref_lambda: 11
by_val_lambda: 11
by_ref_lambda: 12

你想到了么???那這又是為什么呢?為什么第三個輸出不是12呢?

在by_val_lambda中,j被視為一個常量,一旦初始化后不會再改變(可以認為之后只是一個跟父作用域中j同名的常量),而在by_ref_lambda中,j仍然在使用父作用域中的值。所以,在使用Lambda函數的時候,如果需要捕捉的值成為Lambda函數的常量,我們通常會使用按值傳遞的方式捕捉;相反的,如果需要捕捉的值成成為Lambda函數運行時的變量,則應該采用按引用方式進行捕捉。

再來一段更暈的代碼:

復制代碼 代碼如下:

#include<iostream>                 
using namespace std;               
                                   
int main()                         
{                                  
    int val = 0;                                   
    // auto const_val_lambda = [=](){ val = 3; }; wrong!!!
                                   
    auto mutable_val_lambda = [=]() mutable{ val = 3; };
    mutable_val_lambda();          
    cout<<val<<endl; // 0
                                   
    auto const_ref_lambda = [&]() { val = 4; };
    const_ref_lambda();            
    cout<<val<<endl; // 4
                                   
    auto mutable_ref_lambda = [&]() mutable{ val = 5; };
    mutable_ref_lambda();          
    cout<<val<<endl; // 5
                                   
    return 0;     
}

這段代碼主要是用來理解Lambda表達式中的mutable關鍵字的。默認情況下,Lambda函數總是一個const函數,mutable可以取消其常量性。按照規定,一個const的成員函數是不能在函數體內修改非靜態成員變量的值。例如上面的Lambda表達式可以看成以下仿函數代碼:

復制代碼 代碼如下:

class const_val_lambda
{
public:
    const_val_lambda(int v) : val(v) {}
    void operator()() const { val = 3; } // 常量成員函數
 
private:
    int val;
};

對于const的成員函數,修改非靜態的成員變量,所以就出錯了。而對于引用的傳遞方式,并不會改變引用本身,而只會改變引用的值,因此就不會報錯了。都是一些糾結的規則。慢慢理解吧。

總結

對于Lambda這種東西,有的人用的非常爽,而有的人看著都不爽。仁者見仁,智者見智。不管怎么樣,作為程序員的你,都要會的。這篇文章就是用來彌補自己對C++ Lambda表達式的認知不足的過錯,以免以后在別人的代碼中看到了Lambda,還看不懂這種東西,那就丟大人了。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
在线日韩日本国产亚洲| 亚洲精品98久久久久久中文字幕| 伊人亚洲福利一区二区三区| 日韩欧美主播在线| 欧美高清一级大片| 精品视频在线导航| 欧美激情在线有限公司| 国产亚洲精品综合一区91| 欧美一区视频在线| 欧美日韩裸体免费视频| 国产99久久精品一区二区 夜夜躁日日躁| 粉嫩老牛aⅴ一区二区三区| 久久免费高清视频| 97在线免费视频| 亚洲国产日韩欧美在线图片| 久久久黄色av| 国产第一区电影| 国内成人精品视频| 91精品国产99| 亚洲欧美一区二区精品久久久| 8x拔播拔播x8国产精品| 激情久久av一区av二区av三区| 欧美大片免费观看| 亚洲欧美制服丝袜| 国产精品一区二区三区久久| 91免费高清视频| 97超视频免费观看| 日韩极品精品视频免费观看| 中文在线不卡视频| 欧美色道久久88综合亚洲精品| 在线成人免费网站| 韩国三级日本三级少妇99| 欧美激情喷水视频| 国产福利精品av综合导导航| 亚洲自拍在线观看| 色天天综合狠狠色| 久久艳片www.17c.com| 福利视频一区二区| 国产亚洲精品久久| 久久天天躁狠狠躁夜夜躁2014| 亚洲视频在线视频| 免费av在线一区| 欧美最猛性xxxxx(亚洲精品)| 国产一区私人高清影院| 亚洲欧洲黄色网| 精品福利樱桃av导航| 在线观看欧美视频| 久久久国产精品亚洲一区| 91久久久国产精品| 国产a∨精品一区二区三区不卡| 精品视频在线导航| 久久精品国产一区二区电影| 国产视频在线观看一区二区| 欧美日韩在线观看视频小说| 亚洲美女激情视频| 欧美激情一级二级| 欧美精品在线观看91| 国产日产欧美精品| 97人人模人人爽人人喊中文字| 影音先锋日韩有码| 亚洲欧美一区二区三区久久| 亚洲欧美制服中文字幕| 欧美日韩在线观看视频小说| 午夜精品久久久久久99热软件| 久久视频在线观看免费| 欧美日本亚洲视频| 日韩av免费一区| 亚洲精品久久久久久久久久久久久| 欧美亚洲成人精品| 川上优av一区二区线观看| 日本乱人伦a精品| 亚洲丁香婷深爱综合| 久久久久久久电影一区| 日本国产欧美一区二区三区| 亚洲欧美国产制服动漫| 国产精品视频白浆免费视频| 一区二区三区亚洲| 国产精品亚洲自拍| 欧美电影免费观看电视剧大全| 欧美专区日韩视频| 精品国产美女在线| 亚洲r级在线观看| 日韩高清电影好看的电视剧电影| 国产精品亚洲激情| 91色p视频在线| 成人黄色片在线| 国产一区视频在线播放| 久久国产精品首页| 日韩va亚洲va欧洲va国产| 操91在线视频| 91国内精品久久| 中文字幕精品久久| 亚洲精品福利在线观看| 亚洲精品xxx| 亚洲国产中文字幕久久网| 亚洲加勒比久久88色综合| 中文字幕av一区中文字幕天堂| 91精品国产99久久久久久| 色狠狠久久aa北条麻妃| 欧美交受高潮1| 亚洲精品电影网在线观看| 九九精品视频在线观看| 国产精品福利久久久| 26uuu另类亚洲欧美日本一| 欧美午夜视频一区二区| 91美女片黄在线观看游戏| 亚洲aⅴ日韩av电影在线观看| 亚洲精品午夜精品| 日本不卡免费高清视频| 久久久久久高潮国产精品视| 日韩高清电影免费观看完整版| 日韩av观看网址| 日韩视频免费看| 国产精品青青在线观看爽香蕉| 国产精品色视频| 国产一区二区三区高清在线观看| 中文字幕日韩视频| 亚洲成色999久久网站| 亚洲美女又黄又爽在线观看| 欧美电影第一页| 国产欧美一区二区三区在线| 国产美女精品视频| 国产成人+综合亚洲+天堂| 国产九九精品视频| 91亚洲精品久久久久久久久久久久| 国产91在线播放九色快色| 久久91超碰青草是什么| 国产精品久久久久久久久久东京| 日本欧美中文字幕| 亚洲欧美日韩中文在线| 日韩中文字幕精品视频| 亚洲香蕉成人av网站在线观看| 欧美成人激情视频免费观看| 国产性猛交xxxx免费看久久| 国产欧美精品一区二区| 欧美激情视频三区| 亚洲精品久久久久久久久久久久久| 亚洲97在线观看| 国产精品美女久久久久av超清| 日韩欧美中文字幕在线播放| 欧美有码在线视频| 日韩av高清不卡| 91日本视频在线| 亚洲第一视频在线观看| 日韩欧美中文字幕在线播放| 国产欧美在线播放| 26uuu国产精品视频| 国产精品扒开腿做爽爽爽视频| 国产99在线|中文| 91久久久亚洲精品| 69久久夜色精品国产7777| 欧美日韩免费观看中文| 久久精品夜夜夜夜夜久久| 在线精品91av| 中文亚洲视频在线| 欧美激情videoshd| 成人免费xxxxx在线观看| 国内精品久久久久久久久| 最新国产精品亚洲| 亚洲成人教育av| 91在线精品视频| 中文字幕国产精品| 国产亚洲精品成人av久久ww| 亚洲人成人99网站|