C++ lambda 用法


1. 為什么要使用lambda
  + 就地匿名的定義一個目標函數或者函數對象,不需要額外的再寫一個命名函數或者函數對象,以更直接的方式去寫函數,可以調高程序的可讀性和可維護性。
  + 簡潔:不要額外的的再寫一個函數或者函數對象,避免了代碼膨脹或者功能分散。
  + 在需要的時間或者地點實現功能閉包,是程序更加靈活。

2. lambda 的語法
  + [capture] (parameters) mutable->return-type{statement};
3. lambda 的內部實現
  + 編譯器會自動生成一個匿名類,該類重載了 () 運算符。

 

    int id = 0;
    auto f = [id]() mutable {
        cout << "id: " << id << endl;
        ++id;
    };

  

+ 當寫出上面一塊代碼時,那么編譯器就會將他們轉換成以下的代碼

class Functor {
private:
    int id;
public:
    void operator() (){
        std::cout << "id: " << id << endl;
        ++id;
    }
};

 

  + 其中,函數名具體是取決於編譯器自己編譯,私有成員變量是捕獲列表所來,重載的 () 操作符函數具體是由 lambda 表達式 body 所來

4. lambda 的使用
1. 捕獲列表:
  + []:什么也不捕獲
  + [=]: 按值的方式捕獲所有變量
  + [&]: 按引用方式捕獲所有變量
  + [boo]:值捕獲 boo 的值
  + [=, &a]: 按值捕獲所有局部變量,按引用捕獲變量a。
  + [=, &a, &b, &c]:同上,
  + [&, a]:按引用捕獲所有局部變量,按值捕獲方式捕獲 a
  + [&, a, b, c]:同上
  + [this]:在成員函數中,直接捕獲 this 指針
2. mutable:
  + 值捕獲后,在匿名函數中對該值是不能做修改的,如果想要做修改,必須加上 mutable 關鍵字,並且在匿名函數中做的修改結果在函數外是不會生效的;
3. parameters:
  + 參數列表也是可以將外部的值傳遞給匿名函數內部的,和捕獲列表的在於,parameter 對應的 operator函數的形參列表。
4. return-tyep:
  + 對於編譯器能自動推導的返回類型,可以省略 return-type,但是如果無法推導的類型,就必須添加上返回類型
  + 當函數不止一個return語句時,就需要加上返回類型了。

+ 總結:
1. 捕獲列表中,捕捉的值會作為類的私有成員生成,且是const類型,所以值捕獲的數值無法在匿名函數中修改,引用捕獲可以修改,且這種改變可以傳到外部。

 

Example:

#include<iostream>

using namespace std;

void capturePassedByValueAll();
void capturePassedByReferenceAll();
void capturePassedByValueExceptSome();
void lambdaMutable();
void lambdaParameter();
void lambdaReturnType();

int main() {

    // passed by value
    capturePassedByValueAll();

    // passed by reference
    capturePassedByReferenceAll();

    // passed by value all excpet some
    capturePassedByValueExceptSome();

    // passed by value all and mutable
    lambdaMutable();

    // lambda in parameter
    lambdaParameter();

    // lambda in return
    lambdaReturnType();


    return 0;
}

void lambdaReturnType()
{  
    auto autoGetRetutnType = []() {
        return 5+3;
    };
    cout  << "lambdaReturnType = " << autoGetRetutnType() << endl;

    auto specifyReturnType = [](int x)->string {
        if (x > 0) {
            return "x more than zero";
        }
        else {
            return "x less than zero";
        }
    };
    cout  << "specifyReturnType = " << specifyReturnType(2) << endl;

}

void lambdaParameter()
{
    int a = 1;
    int b = 2;
    
    auto f = [](int a, int b) {
        return a > b ? a : b;
    };

    cout  << "lambdaParameter f(a,b) = " << f(a, b) << endl;
}

void lambdaMutable()
{
    int a = 1;
    int b = 2;

    auto passedByValueMutable = [=]()mutable {
        cout << "lambdaMutable start a :" << a << " b: " << b << endl;
        a++;
        b++;
        cout << "modify after a :" << a << " b: " << b << endl;
    };
    passedByValueMutable();
    cout << "lambdaMutable a :" << a << " b: " << b << endl;
}

void capturePassedByValueExceptSome()
{
    int a = 0;
    int b = 1;
    int c = 100;
    int d = 200;
    auto passedByValueExceptSome = [=, &c, &d]() {
        cout << "capturePassedByValueExceptSome start a = " << a << " b = " << b << endl;
        cout << "midify after c = " << c << " d = " << d << endl;
        
        c++;
        d++;
        cout << "midify after c = " << c << " d = " << d << endl;
        cout << "capturePassedByValueExceptSome end" << endl;

    };

    passedByValueExceptSome();
    cout << "a = " << a << " b = " << b << endl;    
}

void capturePassedByReferenceAll()
{
    int c = 100;
    int d = 200;
    auto passedByReference = [&] {
        cout << "passedByReference c = " << c << " d = " << d << endl;
        c++;
        d++;
        cout << "c = " << c << " d = " << d << endl;
        cout << "passedByReference end" << endl;
    };
    passedByReference();
    cout << "c = " << c << " d = " << d << endl;
}

void capturePassedByValueAll()
{
    int a = 0;
    int b = 1;
    auto passedByValue = [=]() {
        cout << "passedByValue start a = " << a << " b = " << b << endl;
        cout << "passedByValue end" << endl;
    };

    passedByValue();
    cout << "a = " << a << " b = " << b << endl;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM