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

C++中的Lambda表達(dá)式詳解

 更新時(shí)間:2014年10月13日 08:53:52   投稿:junjie  
這篇文章主要介紹了C++中的Lambda表達(dá)式詳解,本文講解了基本語(yǔ)法、Lambda的使用等內(nèi)容,需要的朋友可以參考下

我是搞C++的

一直都在提醒自己,我是搞C++的;但是當(dāng)C++11出來(lái)這么長(zhǎng)時(shí)間了,我卻沒(méi)有跟著隊(duì)伍走,發(fā)現(xiàn)很對(duì)不起自己的身份,也還好,發(fā)現(xiàn)自己也有段時(shí)間沒(méi)有寫(xiě)C++代碼了。今天看到了C++中的Lambda表達(dá)式,雖然用過(guò)C#的,但是C++的,一直沒(méi)有用,也不知道怎么用,就可憐的連Lambda語(yǔ)法都看不懂。好了,這里就對(duì)C++中的Lambda進(jìn)行一個(gè)簡(jiǎn)單的總結(jié),就算是對(duì)自己的一個(gè)交代,我是搞C++的,我是一個(gè)C++ programmer。

一段簡(jiǎn)單的Code

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

復(fù)制代碼 代碼如下:

#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;
}

當(dāng)我第一次看到這段代碼時(shí),我直接凌亂了,直接看不懂啊。上面這段代碼,如果你看懂了,下面的內(nèi)容就當(dāng)時(shí)復(fù)習(xí)了;如果看不懂了,就接著和我一起總結(jié)吧。

基本語(yǔ)法

簡(jiǎn)單來(lái)說(shuō),Lambda函數(shù)也就是一個(gè)函數(shù),它的語(yǔ)法定義如下:

復(fù)制代碼 代碼如下:

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

1.[capture]:捕捉列表。捕捉列表總是出現(xiàn)在Lambda函數(shù)的開(kāi)始處。實(shí)際上,[]是Lambda引出符。編譯器根據(jù)該引出符判斷接下來(lái)的代碼是否是Lambda函數(shù)。捕捉列表能夠捕捉上下文中的變量以供Lambda函數(shù)使用;

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

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

4.->return-type:返回類(lèi)型。用追蹤返回類(lèi)型形式聲明函數(shù)的返回類(lèi)型。我們可以在不需要返回值的時(shí)候也可以連同符號(hào)”->”一起省略。此外,在返回類(lèi)型明確的情況下,也可以省略該部分,讓編譯器對(duì)返回類(lèi)型進(jìn)行推導(dǎo);

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

與普通函數(shù)最大的區(qū)別是,除了可以使用參數(shù)以外,Lambda函數(shù)還可以通過(guò)捕獲列表訪問(wèn)一些上下文中的數(shù)據(jù)。具體地,捕捉列表描述了上下文中哪些數(shù)據(jù)可以被Lambda使用,以及使用方式(以值傳遞的方式或引用傳遞的方式)。語(yǔ)法上,在“[]”包括起來(lái)的是捕捉列表,捕捉列表由多個(gè)捕捉項(xiàng)組成,并以逗號(hào)分隔。捕捉列表有以下幾種形式:

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

上面提到了一個(gè)父作用域,也就是包含Lambda函數(shù)的語(yǔ)句塊,說(shuō)通俗點(diǎn)就是包含Lambda的“{}”代碼塊。上面的捕捉列表還可以進(jìn)行組合,例如:

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

不過(guò)值得注意的是,捕捉列表不允許變量重復(fù)傳遞。下面一些例子就是典型的重復(fù),會(huì)導(dǎo)致編譯時(shí)期的錯(cuò)誤。例如:

3.[=,a]這里已經(jīng)以值傳遞方式捕捉了所有變量,但是重復(fù)捕捉a了,會(huì)報(bào)錯(cuò)的;
4.[&,&this]這里&已經(jīng)以引用傳遞方式捕捉了所有變量,再捕捉this也是一種重復(fù)。

Lambda的使用

對(duì)于Lambda的使用,說(shuō)實(shí)話,我沒(méi)有什么多說(shuō)的,個(gè)人理解,在沒(méi)有Lambda之前的C++ , 我們也是那樣好好的使用,并沒(méi)有對(duì)缺少Lambda的C++有什么抱怨,而現(xiàn)在有了Lambda表達(dá)式,只是更多的方便了我們?nèi)?xiě)代碼。不知道大家是否記得C++ STL庫(kù)中的仿函數(shù)對(duì)象,仿函數(shù)想對(duì)于普通函數(shù)來(lái)說(shuō),仿函數(shù)可以擁有初始化狀態(tài),而這些初始化狀態(tài)是在聲明仿函數(shù)對(duì)象時(shí),通過(guò)參數(shù)指定的,一般都是保存在仿函數(shù)對(duì)象的私有變量中;在C++中,對(duì)于要求具有狀態(tài)的函數(shù),我們一般都是使用仿函數(shù)來(lái)實(shí)現(xiàn),比如以下代碼:

復(fù)制代碼 代碼如下:

#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; // 發(fā)現(xiàn)C++11中,enum類(lèi)型的使用也變了,更“強(qiáng)”了                                                                                                                                             
    return 0;
}

現(xiàn)在我們有了Lambda這個(gè)利器,那是不是可以重寫(xiě)上面的實(shí)現(xiàn)呢?看代碼:

復(fù)制代碼 代碼如下:

#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;
}

顯而易見(jiàn)的效果,代碼簡(jiǎn)單了,你也少寫(xiě)了一些代碼,也去試一試C++中的Lambda表達(dá)式吧。

關(guān)于Lambda那些奇葩的東西

看以下一段代碼:

復(fù)制代碼 代碼如下:

#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;             
}

程序輸出結(jié)果如下:

復(fù)制代碼 代碼如下:

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

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

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

再來(lái)一段更暈的代碼:

復(fù)制代碼 代碼如下:

#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;     
}

這段代碼主要是用來(lái)理解Lambda表達(dá)式中的mutable關(guān)鍵字的。默認(rèn)情況下,Lambda函數(shù)總是一個(gè)const函數(shù),mutable可以取消其常量性。按照規(guī)定,一個(gè)const的成員函數(shù)是不能在函數(shù)體內(nèi)修改非靜態(tài)成員變量的值。例如上面的Lambda表達(dá)式可以看成以下仿函數(shù)代碼:

復(fù)制代碼 代碼如下:

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

對(duì)于const的成員函數(shù),修改非靜態(tài)的成員變量,所以就出錯(cuò)了。而對(duì)于引用的傳遞方式,并不會(huì)改變引用本身,而只會(huì)改變引用的值,因此就不會(huì)報(bào)錯(cuò)了。都是一些糾結(jié)的規(guī)則。慢慢理解吧。

總結(jié)

對(duì)于Lambda這種東西,有的人用的非常爽,而有的人看著都不爽。仁者見(jiàn)仁,智者見(jiàn)智。不管怎么樣,作為程序員的你,都要會(huì)的。這篇文章就是用來(lái)彌補(bǔ)自己對(duì)C++ Lambda表達(dá)式的認(rèn)知不足的過(guò)錯(cuò),以免以后在別人的代碼中看到了Lambda,還看不懂這種東西,那就丟大人了。

相關(guān)文章

  • Qt實(shí)現(xiàn)簡(jiǎn)單UDP通信

    Qt實(shí)現(xiàn)簡(jiǎn)單UDP通信

    這篇文章主要為大家詳細(xì)介紹了Qt實(shí)現(xiàn)簡(jiǎn)單UDP通信,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • C++實(shí)現(xiàn)并查集

    C++實(shí)現(xiàn)并查集

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)并查集,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • 一文帶你了解C語(yǔ)言中static關(guān)鍵字的3個(gè)作用

    一文帶你了解C語(yǔ)言中static關(guān)鍵字的3個(gè)作用

    static這個(gè)關(guān)鍵字是“靜態(tài)”的意思,在C語(yǔ)言里主要有3個(gè)作用。這篇文章主要通過(guò)一些簡(jiǎn)單示例為大家詳細(xì)講講這3個(gè)左右,感興趣的小伙伴可以了解一下
    2023-04-04
  • 基于Matlab實(shí)現(xiàn)抖音小游戲蘋(píng)果蛇

    基于Matlab實(shí)現(xiàn)抖音小游戲蘋(píng)果蛇

    最近抖音上蘋(píng)果蛇小游戲大火,為了證明MATLAB無(wú)所不能,咋能不跟風(fēng)做一個(gè)?文中詳細(xì)講解了游戲的實(shí)現(xiàn)步驟,感興趣的小伙伴可以嘗試一下
    2022-06-06
  • VC++實(shí)現(xiàn)輸出GIF到窗體并顯示GIF動(dòng)畫(huà)的方法

    VC++實(shí)現(xiàn)輸出GIF到窗體并顯示GIF動(dòng)畫(huà)的方法

    這篇文章主要介紹了VC++實(shí)現(xiàn)輸出GIF到窗體并顯示GIF動(dòng)畫(huà)的方法,需要的朋友可以參考下
    2014-07-07
  • C語(yǔ)言實(shí)現(xiàn)字符串字符反向排列的方法詳解

    C語(yǔ)言實(shí)現(xiàn)字符串字符反向排列的方法詳解

    這篇文章主要為大家分享了幾種通過(guò)C語(yǔ)言實(shí)現(xiàn)字符串字符反向排列(不是逆序打印)的方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2022-05-05
  • C++實(shí)例分析講解臨時(shí)對(duì)象與右值引用的用法

    C++實(shí)例分析講解臨時(shí)對(duì)象與右值引用的用法

    對(duì)性能來(lái)說(shuō),許多的問(wèn)題都需要和出現(xiàn)頻率及本身執(zhí)行一次的開(kāi)銷(xiāo)掛鉤,有些問(wèn)題雖然看似比較開(kāi)銷(xiāo)較大,但是很少會(huì)執(zhí)行到,那也不會(huì)對(duì)程序有大的影響;同樣一個(gè)很小開(kāi)銷(xiāo)的函數(shù)執(zhí)行很頻繁,同樣會(huì)對(duì)程序的執(zhí)行效率有很大影響。本章中作者主要根據(jù)臨時(shí)對(duì)象來(lái)闡述這樣一個(gè)觀點(diǎn)
    2022-08-08
  • 利用Matlab實(shí)現(xiàn)迭代適應(yīng)點(diǎn)算法

    利用Matlab實(shí)現(xiàn)迭代適應(yīng)點(diǎn)算法

    道格拉斯-普克算法(Douglas–Peucker?algorithm,亦稱(chēng)為拉默-道格拉斯-普克算法、迭代適應(yīng)點(diǎn)算法、分裂與合并算法)是將曲線近似表示為一系列點(diǎn),并減少點(diǎn)的數(shù)量的一種算法。本文將利用Matlab實(shí)現(xiàn)這一算法,需要的可以參考一下
    2022-04-04
  • C/C++實(shí)現(xiàn)segy文件的讀取詳解

    C/C++實(shí)現(xiàn)segy文件的讀取詳解

    SEGY是地震數(shù)據(jù)一般以地震道為單位進(jìn)行組織,采用SEG-Y文件格式存儲(chǔ)。標(biāo)準(zhǔn)SEGY文件一般包括三部分:卷頭、道頭與地震道數(shù)據(jù)。本文將介紹利用C++讀取segy文件的方法,感興趣的可以了解一下
    2022-03-03
  • OPENCV批量讀取圖片實(shí)現(xiàn)方法

    OPENCV批量讀取圖片實(shí)現(xiàn)方法

    下面小編就為大家?guī)?lái)一篇OPENCV批量讀取圖片實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的?,F(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-06-06

最新評(píng)論

肇州县| 铅山县| 遵义县| 息烽县| 罗定市| 舒城县| 克拉玛依市| 寿阳县| 自治县| 南丰县| 博罗县| 徐水县| 平谷区| 姜堰市| 闽清县| 仁怀市| 新余市| 高唐县| 砀山县| 海南省| 镶黄旗| 岳西县| 庆阳市| 芜湖县| 察哈| 法库县| 日喀则市| 江陵县| 贵德县| 罗平县| 锡林郭勒盟| 壤塘县| 合阳县| 南川市| 江孜县| 肇源县| 博客| 中牟县| 灌南县| 辽阳县| 那曲县|