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

一文詳解C++11中的lambda函數(shù)

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

我可以明確告訴你:lambda函數(shù)是C++11中最重要的,使用最廣泛的,最具現(xiàn)代風格的內(nèi)容,lambda函數(shù)的出現(xiàn)改變了C++編程的思維方式。

#include<iostream>
using namespace std;
int main()
{
    int girls=3,boys=4;
    auto totalChild=[](int x,int y)->int{return x+y;};
    return totalChild(girls,boys);
}

上面中,auto和lambda函數(shù)的配合是一種經(jīng)典生成局部函數(shù)的方法。lambda函數(shù)和普通函數(shù)最大的不同的地方就是它沒有名字,所以 lambda函數(shù)是右值。

lambda函數(shù)相較于,函數(shù)指針,仿函數(shù),它不僅簡單,而且效率高。

1.lambda函數(shù)語法

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

  • [capture]:捕捉列表。捕獲父作用域中可用的變量,供lambda函數(shù)使用,[]是lambda函數(shù)的導出符號。
  • (parameters):參數(shù)列表。和普通函數(shù)的參數(shù)列表一樣,如果沒有參數(shù)可以省略
  • mutable:修飾符號。lambda函數(shù)默認是一個const修飾的函數(shù),mutab可以取消其常量性
  • ->return-type:返回類型。類似于返回值后置的語法,如果沒有返回值或者返回類型可自動推斷就可省略聲明返回類型。
  • {statement}:函數(shù)體。

根據(jù)上面語法,我們知道[]{}是一種最簡單的lambda函數(shù),而且我們發(fā)現(xiàn),從語法角度來看,lambda函數(shù)比普通函數(shù)多了一個捕獲列表,這是它的精髓所在。

1.1 捕獲列表

int main()
{
    []{};//最簡單的lambda函數(shù)
    int a=3;
    int b=4;
    [=]{return a+b;};
    auto func1=[&](int c){b=a+c;};
    auto func2=[=,&b](int c)->int{return b+=a+c;};
}。

上面代碼中,我們可以使用捕獲列表來捕獲,變量a和b

被捕獲的變量和基于參數(shù)傳遞的變量是不同的,被捕獲的變量更是一種lambda函數(shù)的初始狀態(tài)。

捕獲列表是由多個捕獲項組成的:

  • [var]:表示按值方式捕獲變量var
  • [=]:表示按值捕獲其父作用域中所有可用的變量(包括this)
  • [&var]:表示按引用捕獲變量var
  • [&]:表示按引用捕獲其父作用域中所有可用的變量(包括this)
  • [this]:表示按值傳遞當前的this指針

特別的這些捕獲項可用組合使用,例如:[=,&a,&b]表示以引用捕獲a和b,按值捕獲其他所有變量。[&,a,this]表示按值捕獲a和this,按引用捕獲其他所有變量。

下面看一段代碼

#include<iostream>
using namespace std;

int main()
{
    int j=12;
    auto fun1=[=]{return j;};
    auto fun2=[&]{return j;};
    cout<<"fun1: "<<fun1()<<endl;
    cout<<"fun2: "<<fun2()<<endl;

    j++;
    cout<<"fun1: "<<fun1()<<endl;
    cout<<"fun2: "<<fun2()<<endl;
}
/*
fun1: 12
fun2: 12
fun1: 12
fun2: 13
*/

當j++后,再次調(diào)用func1()時,我們發(fā)現(xiàn)它里面的j卻保持不變,所以上面這段代碼反應了一個事實:捕獲的變量是lambda函數(shù)的初始狀態(tài)。

在使用lambda函數(shù)時,按值傳遞的變量成為函數(shù)中的常量,它不會再運行過程中改變,按引用傳遞的變量,它類似于函數(shù)參數(shù),他會隨時檢查其值。

#include<iostream>
using namespace std;
int temp=0;
int main()
{
    static int a=0;
    auto fun=[]{temp++;a++;};
    fun();
    fun();
    cout<<temp<<endl;//2
    cout<<a<<endl;//2;

    [temp]{};//編譯錯誤
    [a]{};//編譯錯誤
}

lambda函數(shù)中也可以直接使用全局變量,但是如果fun1這樣就是錯誤的,因為 lambda函數(shù)只能捕獲其父作用域中可用的自動變量,而靜態(tài)變量不需要捕獲,可以直接使用。

#include<iostream>
using namespace std;
int main()
{
    int a=1;
    cout<<"a="<<a<<endl;
    auto foo1=[&]()
    {
        a++;
        cout<<"a="<<a<<endl;
        auto foo2=[&]()
        {
            a++;
            cout<<"a="<<a<<endl;
        };
        foo2();
    };
    foo1();
}
/*
a=1
a=2
a=3
*/

上面代碼中說明,lambda函數(shù)中還可以使用lambda函數(shù),這樣子,上面代碼就狠像pascal語言中的內(nèi)嵌函數(shù)。

1.2 mutable修飾符

lambda函數(shù)是具有常量性的,下面這段代碼是在stackoverflow網(wǎng)站中的一次討論:

int main()
{
    int val;
    auto fun1=[=]{val=3;};//編譯失敗,val無法被賦值
    auto fun2=[=]() mutable {val=3;};
    auto fun3=[&]{val=3;};
    auto fun4=[](int v){v=3;};
    fun4(val);
}

上面中,fun1無法通過編譯,因為val是按值傳遞的,所以在函數(shù)體中,val就是一個只讀常量,無法對其進行賦值,我們可以使用修飾符mutable來取消其只讀屬性。這樣的目的是只是提供一種語法上的可能,在實際使用的時候,我們一般不需要使用mutable,如果需要修改按值傳遞的值,我們可以直接按值傳遞參數(shù),而不是捕獲它。

實際上,lambda函數(shù)中的捕獲變量,更像是函數(shù)對象(仿函數(shù))中的私有數(shù)據(jù)成員:

class fun1
{
private:
    int val;
public:
    fun1(int v):val(v){};
    void operator()const{val=3;};//編譯出錯
}

默認情況下,按值捕獲的變量,如果不加mutable,它就會等價于上面的仿函數(shù),這里的operator()就是const修飾的,它不允許修改val。

1.3 匿名lambda函數(shù)

lambda函數(shù)本身是右值,它沒有名字,它本身就是匿名的,我們一般通過auto來賦予它一個名字,這樣就能生成類似一個局部函數(shù)的效果。我們也可以不使用auto,我們可以直接生成一個lambda函數(shù),然后調(diào)用,例如下面這段代碼:

#include<iostream>
using namespace std;

int main()
{
    const int a=[]{
        int ret=0;
        for(int i=0;i<100;i++)
        {
            ret+=i;
        }
        return ret;
    }();
    cout<<a<<endl;
}

lambda函數(shù)定義后直接調(diào)用。

實際上,lambda函數(shù)的設(shè)計初衷就是:就地書寫,就地使用。所以諸如上面的寫法非常常見。

2.lambda與STL

lambda函數(shù)的出現(xiàn),讓我們發(fā)現(xiàn)使用STL算法更加簡單了。

例如for_each()算法,它接收3個參數(shù),前兩個是指示范圍的迭代器類型,第3個是接收一個參數(shù)的函數(shù)符(即仿函數(shù),函數(shù)指針,lambda函數(shù))。

#include<vector>
#include<algorithm>
#include<iostream>
using namespace std;
extern vector<int> nums;

void OneCond(int val)
{
    //傳統(tǒng)for方法
    for(auto i=nums.begin();i!=nums.end();++i)
    {
        if(*i==val)
            break;
    }
    //使用adapter
    find_if(nums.begin(),nums.end(),bind2nd(equal_to<int>(),val));
    //使用lambda函數(shù)
    find_if(nums.begin(),nums.end(),[=](int i){
        return i==val;
    });
}

上面代碼中,有些人認為使用這種adapter會簡單一點,就像這里的equal_to<int>()它就是是一個函數(shù)對象,我只能說仁者見仁。但是這種使用adapter的方式創(chuàng)建函數(shù)對象,要求程序員懂很多STL的知識,而且可讀性不好,例如下面這段代碼

#include<vector>
#include<algorithm>
#include<iostream>
using namespace std;

extern vector<int> nums;

void twoCond(int low,int high)
{
    for(auto i=nums.begin();i!=nums.end();i++)
    {
        if(*i>=low && *i<high)break;
    }
    find_if(nums.begin(),nums.end(),compose2(
        logical_and<bool>(),
        bind2nd(less<int>(),high),
        bind2nd(greater_equal<int>(),low)
    ));
    find_if(nums.begin(),nums.end(),[=](int i)
    {
        return i>=low && i<high;
    });
}

再看看下面的lambda簡化STL的例子

#include<vector>
#include<algorithm>
#include<iostream>
using namespace std;

vector<int> nums;
void Add(const int val)
{
    auto print =[]{
        for(auto s:nums)
        {
            cout<<s<<"\t";
        }
        cout<<endl;
    };
    for(auto i=nums.begin();i!=nums.end();i++)
    {
        *i=*i+val;
    }
    print();

    for_each(nums.begin(),nums.end(),bind2nd(plus<int>(),val));
    print();

    transform(nums.begin(),nums.end(),nums.begin(),bind2nd(plus<int>(),val));
    print();

    for_each(nums.begin(),nums.end(),[=](int &i){i+=val;});
    print();
}
int main()
{
    for(int i=0;i<10;i++)
    nums.emplace_back(i);
    Add(10);
}
/*
10      11      12      13      14      15      16      17      18      19
10      11      12      13      14      15      16      17      18      19
20      21      22      23      24      25      26      27      28      29
30      31      32      33      34      35      36      37      38      39
*/

我們發(fā)現(xiàn)上面代碼運行后,第二行相較于第一行沒有變化,如果熟悉STL,你會狠容易發(fā)現(xiàn),因為for_each()它不會寫回,而transform它會寫回。STL新手就會容易犯這個錯誤,如果你使用lambda函數(shù)這些東西就不需要了。

#include<vector>
#include<algorithm>
#include<iostream>
#include<numeric>
using namespace std;

void Stat(vector<int> &v)
{
    int errors;
    int score;
    auto print =[&]{
        cout<<"Errors: "<<errors<<endl
        <<"Score: "<<score<<endl;
    };
    errors=accumulate(v.begin(),v.end(),0);
    score=accumulate(v.begin(),v.end(),100,minus<int>());
    print();

    errors=0;
    score=100;

    for_each(v.begin(),v.end(),[&](int i){
        errors+=i;
        score-=i;
    });
    print();
}

int main()
{
    vector<int> v(10);
    generate(v.begin(),v.end(),[]{return rand()&10;});
    Stat(v);
}

總之,lambda函數(shù)非常好用

以上就是一文詳解C++11中的lambda函數(shù)的詳細內(nèi)容,更多關(guān)于C++11 lambda函數(shù)的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C++中的vector使用詳解及重要部分底層實現(xiàn)

    C++中的vector使用詳解及重要部分底層實現(xiàn)

    本篇文章會對vector的語法使用進行詳解,同時,還會對重要難點部分的底層實現(xiàn)進行講解,其中有vector的迭代器失效和深拷貝問題,希望本篇文章的內(nèi)容會對你有所幫助
    2023-07-07
  • VC動態(tài)生成菜單項的實現(xiàn)方法

    VC動態(tài)生成菜單項的實現(xiàn)方法

    這篇文章主要介紹了VC動態(tài)生成菜單項的實現(xiàn)方法,在桌面應用程序開發(fā)中常會用到的一個功能,需要的朋友可以參考下
    2014-08-08
  • C++中對象的動態(tài)建立與釋放詳解及其作用介紹

    C++中對象的動態(tài)建立與釋放詳解及其作用介紹

    這篇文章主要介紹了C++中對象的動態(tài)建立與釋放詳解及其作用介紹,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-09-09
  • C++語言實現(xiàn)開心消消樂

    C++語言實現(xiàn)開心消消樂

    這篇文章主要為大家詳細介紹了C++語言實現(xiàn)開心消消樂,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • C++實現(xiàn)LeetCode(135.分糖果問題)

    C++實現(xiàn)LeetCode(135.分糖果問題)

    這篇文章主要介紹了C++實現(xiàn)LeetCode(135.分糖果問題),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • C語言編程大小端問題示例詳解教程

    C語言編程大小端問題示例詳解教程

    這篇文章主要為大家介紹了C語言編程大小端問題解決的示例內(nèi)容詳解教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步
    2021-11-11
  • C++快速調(diào)用DeepSeek API的完整指南

    C++快速調(diào)用DeepSeek API的完整指南

    最近,DeepSeek的API引起了我的興趣,它提供了強大的對話生成能力,可以用于多種應用場景,雖然DeepSeek官方提供了詳細的API文檔,但遺憾的是,目前沒有專門針對C++的調(diào)用示例,所以,本文給大家實現(xiàn)一個C++版本的調(diào)用示例,需要的朋友可以參考下
    2025-03-03
  • Visual Studio Code運行C++代碼時顯示CLOCKS_PER_SEC未定義的問題及解決方法

    Visual Studio Code運行C++代碼時顯示CLOCKS_PER_SEC未定義的問題及解決方法

    這篇文章主要介紹了解決Visual Studio Code運行C++代碼時顯示CLOCKS_PER_SEC未定義的問題,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-04-04
  • C++制作《游戲內(nèi)存外掛》詳解

    C++制作《游戲內(nèi)存外掛》詳解

    這篇文章主要介紹了C++制作《游戲內(nèi)存外掛》詳解,文中通過示例代碼和圖片介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-07-07
  • iOS鎖屏音頻播放控制及音頻信息設(shè)置

    iOS鎖屏音頻播放控制及音頻信息設(shè)置

    這篇文章主要為大家詳細介紹了iOS鎖屏音頻播放控制及音頻信息設(shè)置,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-12-12

最新評論

鄂温| 台前县| 武威市| 广元市| 黄平县| 亚东县| 营山县| 伊川县| 和政县| 平江县| 河西区| 武平县| 张家川| 泰宁县| 晋州市| 新余市| 湟中县| 高淳县| 罗源县| 越西县| 铁力市| 阿巴嘎旗| 宝鸡市| 闻喜县| 涿鹿县| 溧阳市| 海门市| 汤原县| 武川县| 深水埗区| 永新县| 苍梧县| 肥东县| 黎平县| 常州市| 石嘴山市| 大连市| 平陆县| 玛沁县| 深圳市| 聂拉木县|