lambda表示式 lambda表示式

2021-10-11 13:53:40 字數 2691 閱讀 9365

1. 概述

c++ 11 中的 lambda 表示式用於定義並建立匿名的函式物件,以簡化程式設計工作。 lambda 的語法形式如下:

[函式物件引數] (操作符過載函式引數) mutable 或 exception 宣告 -> 返回值型別
可以看到,lambda 主要分為五個部分:[函式物件引數]、(操作符過載函式引數)、mutable 或 exception 宣告、-> 返回值型別、.

標識乙個 lambda 表示式的開始,這部分必須存在,不能省略。函式物件引數是傳遞給編譯器自動生成的函式物件類的構造 函式的。函式物件引數只能使用那些到定義 lambda 為止時 lambda 所在作用範圍內可見的區域性變數(包括 lambda 所在類 的 this)。函式物件引數有以下形式:

標識過載的 () 操作符的引數,沒有引數時,這部分可以省略。引數可以通過按值(如: (a, b))和按引用 (如: (&a, &b)) 兩種 方式進行傳遞。

這部分可以省略。按值傳遞函式物件引數時,加上 mutable 修飾符後,可以修改傳遞進來的拷貝(注意是能修改拷貝,而不是 值本身)。exception 宣告用於指定函式丟擲的異常,如丟擲整數型別的異常,可以使用 throw(int)。

標識函式返回值的型別,當返回值為 void,或者函式體中只有一處 return 的地方(此時編譯器可以自動推斷出返回值型別) 時,這部分可以省略。

標識函式的實現,這部分不能省略,但函式體可以為空。

(int x, int y)  // 隱式返回型別 (int& x)  // 沒有 return 語句 -> lambda 函式的返回型別是 'void' ()  // 沒有引數,僅訪問某個全域性變數  // 與上乙個相同,省略了 (操作符過載函式引數)
可以像下面這樣顯示指定返回型別:

(int x, int y) -> int
在這個例子中建立了乙個臨時變數 z 來儲存中間值。和普通函式一樣,這個中間值不會儲存到下次呼叫。什麼也不返回的 lambda 函式可以省略返回型別,而不需要使用 -> void 形式。

lambda 函式可以引用在它之外宣告的變數. 這些變數的集合叫做乙個閉包. 閉包被定義在 lambda 表示式宣告中的方括 號 內。這個機制允許這些變數被按值或按引用捕獲。如下圖的例子:

std::vector some_list;int total = 0;for (int i = 0; i < 5; ++i) some_list.push_back(i);std::for_each(begin(some_list), end(some_list), [&total](int x));
此例計算 list 中所有元素的總和。變數 total 被存為 lambda 函式閉包的一部分。因為它是棧變數(區域性變數)total 引 用,所以可以改變它的值。

std::vector some_list;int total = 0;int value = 5;std::for_each(begin(some_list), end(some_list), [&, value, this](int x));
此例中 total 會存為引用, value 則會存乙份值拷貝。對 this 的捕獲比較特殊,它只能按值捕獲。this 只有當包含它的最靠近 它的函式不是靜態成員函式時才能**獲。對 protect 和 private 成員來說,這個 lambda 函式與建立它的成員函式有相同 的訪問控制。如果 this **獲了,不管是顯式還是隱式的,那麼它的類的作用域對 lambda 函式就是可見的。訪問 this 的 成員不必使用 this-> 語法,可以直接訪問。

不同編譯器的具體實現可以有所不同,但期望的結果是: 按引用捕獲的任何變數,lambda 函式實際儲存的應該是這些變數在 建立這個 lambda 函式的函式的棧指標,而不是 lambda 函式本身棧變數的引用。不管怎樣,因為大多數 lambda 函式都 很小且在區域性作用中,與候選的內聯函式很類似,所以按引用捕獲的那些變數不需要額外的儲存空間。

如果乙個閉包含有區域性變數的引用,在超出建立它的作用域之外的地方被使用的話,這種行為是未定義的!

lambda 函式是乙個依賴於實現的函式物件型別,這個型別的名字只有編譯器知道. 如果使用者想把 lambda 函式做為乙個引數來 傳遞, 那麼形參的型別必須是模板型別或者必須能建立乙個 std::function 類似的物件去捕獲 lambda 函式.使用 auto 關鍵字 可以幫助儲存 lambda 函式,

auto my_lambda_func = [&](int x) ;auto my_onheap_lambda_func = new auto([=](int x) );
這裡有乙個例子, 把匿名函式儲存在變數、陣列或 vector 中,並把它們當做命名引數來傳遞

乙個沒有指定任何捕獲的 lambda 函式,可以顯式轉換成乙個具有相同宣告形式函式指標.所以,像下面這樣做是合法的:

auto a_lambda_func = (int x) ;void (*func_ptr)(int) = a_lambda_func;func_ptr(4); // calls the lambda

Lambda表示式和Lambda表示式樹

原版來自 linq學習筆記之二 lambda表示式和lambda表示式樹 lambda 表示式 lambda expressions 是linq實現的另一特性。lambda表示式的作用就是使用使用函式式語法,將方法實現關聯到委託例項。在使用查詢表示式 query expressions 時,查詢表示...

關於Lambda表示式

lambda表示式是c 3.0的一種新語法,語法簡潔 為編寫匿名方法提供了更簡明的函式式的句法.我通過乙個示例來說明lambda表示式的原理 lambda表示式和匿名方法都 於委託 我們來看看委託的使用 在c 1.0時 c 2.0時可以使用匿名方法 c 3.0使用lambda表示式 使用lambda...

認識Lambda表示式

lambda表示式的本質是 匿名方法 也即是當編譯我們的程式 時,編譯器 會自動幫我們將 lambda表示式 轉換為 匿名方法 如下例 上面中兩個findall方法的反編譯 如下 string findnamea array.findall names,delegate string v strin...