lambda學習總結(c++ primer 5th)

什麼是謂詞:

謂詞是一個可調用的表達式,返回結果是一個能用作條件的值,分一元謂詞(只接受單一參數)和二元謂詞(接受來年改革參數)。

一個二元謂詞的例子:

//less接受兩個參數
bool less(const string a, const string b)
{
         return a.size() <b.size();
}
//根據word的長短排序
sort(words.cbegin(), words.cend(), less);

Lambda的面向的問題:

根據算法接受一元還是二元謂詞,傳遞給算法的謂詞必須嚴格接受一個或者兩個參數。但是有時希望進行的操作需要更多參數,超出了算法對謂詞的限制。

什麼是lambda表達式:

一般可以向算法傳遞任何類別的可調用對象,可以使函數、函數指針或者是lambda表達式。一個lambda表達式表示一個可調用的代碼單元。可以將其理解爲一個未命名的內斂函數。類似與一般函數,包含一個返回類型,一個參數列表和一個函數體,並可以定義在一般函數的內部。形式:

[capture list](parameter list) -> return type { function body}

捕獲列表是一個lambda所在函數中定義的局部變量列表;其他分別代表:參數列表、返回類型和函數體。與一般函數不同的是lambda必須使用尾置返回來指定返回類型。

說明:尾置返回類型對於返回類型比較複雜的函數最有效,比如返回類型是數組的指針或者數組的引用。尾置返回類型跟在形參列表後面並以一個”->”符號開頭,例如:

 Auto func(int i) ->int(*)[10]//Func接受一個int類型的實參,返回一個指針,該指針指向含有10個整數的數組。

可以忽略參數列表和返回類型,但必須一定包含捕獲列表和函數體:

auto f = []{ return 0; };//定義一個可調用對象f,不接受參數,返回0;  

使用函數調用運算符來調用f:

auto a = f();//將f返回值賦值給變量a

Lambda可以根據函數體的代碼推斷出來返回類型。

Lambda表達式的用法:

向lambda傳遞參數:

與普通函數調用類似,調用一個lambda時給定的實參被用來初始化形參。但是與普通函數不同,lambda不能有默認參數,因此一個lambda調用的實參數目必須與形參數目相等,一旦形參初始化完畢就可以執行函數體了。上邊less()函數改寫的lambda:

[](const string &a, const string &b){ returna.size() < b.size(); }

使用捕獲列表:

一個lambda可以出現在一個函數中,使用其局部變量,但他只能使用那些明確指定的變量。一個lambda通過將局部變量包含在其捕獲列別中來指出將會使用這些變量。可以使用捕獲列表查找第一個長度大於等於sz的元素:

auto wc = find_if(words.begin(),words.end(), [sz](const string &a)
{ return a.size() >= sz;});

要注意lambda捕獲列表不同的捕獲方式:

1、 值捕獲

例:

void func()
{
    int a = 1;
    auto lf = [a]{returna;};
    a =0;
    auto j = f();
    cout << j <<endl;
 }

輸出結果爲1,因爲被捕獲變量的值實在lambda創建時拷貝的,隨後對其修改不會影響到lambda中的值。

2、 引用捕獲:

例:

void func()
{
int a = 1;
auto lf = [&a]{returna;};
a =0;
auto j = f();
cout << j <<endl;
}

輸出結果爲0。因爲lambda函數體內使用此變量時實際上使用的是引用所綁定的對象。使用引用捕獲有一個限制,必須保證被引用的對象在lambda執行的時候是存在的。

3、 隱式捕獲

可以讓編譯器根據lambda中的代碼推斷要使用哪些局部變量,捕獲列表中使用‘&’或‘=’號來告訴編譯器推斷捕獲列表,‘&’表示採用引用方式,‘=’表示採用值捕獲。也可以混合使用隱式捕獲和顯示捕獲,不過在使用的時候捕獲列表中的第一個元素必須是隱式符號‘&’或者‘=’。

Lambda捕獲值可變:

一般情況寫,對於一個值被拷貝的變量,lambda不會改變其值,如果需要改變一個被捕獲的值,需要在參數列表前加上“mutable”關鍵字;

對於引用捕獲的變量,是否可以修改捕獲的變量,取決於聲明該變量是否是const類型的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章