c++ 11 中的 lambda 表示式用於定義並建立匿名的函式物件,以簡化程式設計工作。
語法形式:
[函式物件引數/捕獲] (操作符過載函式引數) mutable 或 exception 宣告 -> 返回值型別
1.[函式物件引數/捕獲]
內容含義
空沒有任何函式物件引數。
=函式體內可以使用 lambda 所在範圍內所有可見的區域性變數(包括 lambda 所在類的 this),並且是值傳遞方式(相當於編譯器自動為我們按值傳遞了所有區域性變數)
&函式體內可以使用 lambda 所在範圍內所有可見的區域性變數(包括 lambda 所在類的 this),並且是引用傳遞方式(相當於是編譯器自動為我們按引用傳遞了所有區域性變數)
this
函式體內可以使用 lambda 所在類中的成員變數。
a將 a 按值進行傳遞。按值進行傳遞時,函式體內不能修改傳遞進來的 a 的拷貝,因為預設情況下函式是 const 的,要修改傳遞進來的拷貝,可以新增 mutable 修飾符
&a將 a 按引用進行傳遞
a,&b
將 a 按值傳遞,b 按引用進行傳遞
=,&a,&b
除 a 和 b 按引用進行傳遞外,其他引數都按值進行傳遞
&,a,b
除 a 和 b 按值進行傳遞外,其他引數都按引用進行傳遞
2.操作符過載函式引數
標識過載的 () 操作符的引數,沒有引數時,這部分可以省略。引數可以通過按值(如: (a, b))和按引用 (如: (&a, &b)) 兩種方式進行傳遞。
3.mutable 或 exception 宣告
這部分可以省略。按值傳遞函式物件引數時,加上 mutable 修飾符後,可以修改傳遞進來的拷貝(注意是能修改拷貝,而不是值本身)。exception 宣告用於指定函式丟擲的異常,如丟擲整數型別的異常,可以使用 throw(int)。
4.-> 返回值型別
標識函式返回值的型別,當返回值為 void,或者函式體中只有一處 return 的地方(此時編譯器可以自動推斷出返回值型別)時,這部分可以省略。
5.標識函式的實現,這部分不能省略,但函式體可以為空。
(int x, int y) // 隱式返回型別
(int& x) // 沒有 return 語句 -> lambda 函式的返回型別是 'void'
() // 沒有引數,僅訪問某個全域性變數
// 與上乙個相同,省略了 (操作符過載函式引數)
可以像下面這樣顯示指定返回型別:
(int x, int y) -> int
在這個例子中建立了乙個臨時變數 z 來儲存中間值。和普通函式一樣,這個中間值不會儲存到下次呼叫。什麼也不返回的lambda 函式可以省略返回型別,而不需要使用 -> void 形式。
lambda 函式可以引用在它之外宣告的變數. 這些變數的集合叫做乙個閉包。閉包被定義在 lambda 表示式宣告中的方括號 內。這個機制允許這些變數被按值或按引用捕獲。如下例:
//未定義變數,試圖在lambada表示式內使用任何外部變數都是錯誤的
[x,&y] //x按值捕獲,y按引用捕獲
[&] //用到任何的外部變數都隱式按引用捕獲
[=] //用到任何的外部變數都隱式按值捕獲
[&,x] //x顯式的按照值捕獲,其他變數按引用捕獲
[=,&z] //z按引用捕獲,其他變數按值捕獲
示例 1:
std::vectorsome_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 引用,所以可以改變它的值。
示例2:
std::vectorsome_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) );
C 學習筆記(十八) 檔案操作
檔案型別 二進位制檔案 檔案以文字的二進位制形式儲存 檔案流類 ifstream 專用於從檔案中讀取資料 ofstream 專用於向檔案中寫入資料 fstream 既可寫也可讀,一般使用fstream類,其標頭檔案是fstream.h 使用open函式,open函式是建立檔案流物件和檔案之間的關聯 ...
oracle學習筆記(十八)
110 談到分割槽的作用。我想有點意識的人都會明白。把乙個大的資料表,分成乙個乙個的處理,這樣做的效果是是顯而易見的。在oltp系統中,這種優勢體現不出來。但是在資料倉儲的系統中,這種優勢則還是相當的明顯的。區間分割槽,雜湊表分割槽,列表分割槽還有組合分割槽。111 區間分割槽。根據條件來進行分割槽...
OpenGL學習筆記(十八)
opengl允許我們修改深度測試中使用的比較運算子。這允許我們來控制opengl什麼時候該通過或丟棄乙個片段,什麼時候去更新深度緩衝。我們可以呼叫gldepthfunc函式來設定比較運算子 或者說深度函式 depth function gldepthfunc gl less 這個函式接受下面的比較運...