lambda表示式配合容器、迭代器使用最佳。
對於c++這門語言來說來說,「lambda表示式」或「匿名函式」這些概念聽起來好像很深奧,但很多高階語言在很早以前就已經提供了lambda表示式的功能,如c#,python等。
宣告lambda表示式
lambda表示式完整的宣告格式如下:
[capture list] (params list) mutable exception-> return type各項具體含義如下
capture list:捕獲外部變數列表
params list:形參列表
mutable指示符:用來說用是否可以修改捕獲的變數
exception:異常設定
return type:返回型別
function body:函式體
此外,我們還可以省略其中的某些成分來宣告「不完整」的lambda表示式,常見的有以下幾種:
序號格式
1[capture list] (params list) -> return type
2[capture list] (params list)
3[capture list]
其中:舉例:
#include
#include
#include
using
namespace
std;
bool cmp(int a, int b)
int main()
; vector
lbvec(myvec);
sort(myvec.begin(), myvec.end(), cmp); // 舊式做法
cout
<< "predicate function:"
<< endl;
for (int it : myvec)
cout
<< it << ' ';
cout
<< endl;
sort(lbvec.begin(), lbvec.end(), (int a, int b) -> bool ); // lambda表示式
cout
<< "lambda expression:"
<< endl;
for (int it : lbvec)
cout
<< it << ' ';
}
在c++11之前,我們使用stl的sort函式,需要提供乙個謂詞函式。如果使用c++11的lambda表示式,我們只需要傳入乙個匿名函式即可,方便簡潔,而且**的可讀性也比舊式的做法好多了。
下面,我們就重點介紹一下lambda表示式各項的具體用法。
捕獲外部變數
lambda表示式可以使用其可見範圍內的外部變數,但必須明確宣告(明確宣告哪些外部變數可以被該lambda表示式使用)。那麼,在**指定這些外部變數呢?lambda表示式通過在最前面的方括號來明確指明其內部可以訪問的外部變數,這一過程也稱過lambda表示式「捕獲」了外部變數。
我們通過乙個例子來直觀地說明一下:
#include
using
namespace
std;
int main()
; f(); // 輸出:123
//或通過「函式體」後面的『()』傳入引數
auto x = (int a)(123);
}
上面這個例子先宣告了乙個整型變數a,然後再建立lambda表示式,該表示式「捕獲」了a變數,這樣在lambda表示式函式體中就可以獲得該變數的值。
類似引數傳遞方式(值傳遞、引入傳遞、指標傳遞),在lambda表示式中,外部變數的捕獲方式也有值捕獲、引用捕獲、隱式捕獲。
1、值捕獲
值捕獲和引數傳遞中的值傳遞類似,**獲的變數的值在lambda表示式建立時通過值拷貝的方式傳入,因此隨後對該變數的修改不會影響影響lambda表示式中的值。
示例如下:
int main()
; a = 321;
f(); // 輸出:123
}
這裡需要注意的是,如果以傳值方式捕獲外部變數,則在lambda表示式函式體中不能修改該外部變數的值。
2、引用捕獲
int main()
; a = 321;
f(); // 輸出:321
}
從示例中可以看出,引用捕獲的變數使用的實際上就是該引用所繫結的物件。
3、隱式捕獲
上面的值捕獲和引用捕獲都需要我們在捕獲列表中顯示列出lambda表示式中使用的外部變數。除此之外,我們還可以讓編譯器根據函式體中的**來推斷需要捕獲哪些變數,這種方式稱之為隱式捕獲。隱式捕獲有兩種方式,分別是[=]和[&]。[=]表示以值捕獲的方式捕獲外部變數,[&]表示以引用捕獲的方式捕獲外部變數。
隱式值捕獲示例:
int main()
; // 值捕獲
f(); // 輸出:123
}
隱式引用捕獲示例:
int main()
; // 引用捕獲
a = 321;
f(); // 輸出:321
}
4、混合方式
上面的例子,要麼是值捕獲,要麼是引用捕獲,lambda表示式還支援混合的方式捕獲外部變數,這種方式主要是以上幾種捕獲方式的組合使用。
到這裡,我們來總結一下:c++11中的lambda表示式捕獲外部變數主要有以下形式:
捕獲形式
說明[ ]
不捕獲任何外部變數
[變數名, …]
預設以值得形式捕獲指定的多個外部變數(用逗號分隔),如果引用捕獲,需要顯示宣告(使用&說明符)
[this]
以值的形式捕獲this指標
[=]以值的形式捕獲所有外部變數
[&]以引用形式捕獲所有外部變數
[=, &x]
變數x以引用形式捕獲,其餘變數以傳值形式捕獲
[&, x]
變數x以值的形式捕獲,其餘變數以引用形式捕獲
修改捕獲變數
前面我們提到過,在lambda表示式中,如果以傳值方式捕獲外部變數,則函式體中不能修改該外部變數,否則會引發編譯錯誤。那麼有沒有辦法可以修改值捕獲的外部變數呢?這是就需要使用mutable關鍵字,該關鍵字用以說明表示式體內的**可以修改值捕獲的變數,示例:
int main()
; // 不會報錯
cout
<< a << endl; // 輸出:123
f(); // 輸出:124
}
lambda表示式的引數
lambda表示式的引數和普通函式的引數類似,那麼這裡為什麼還要拿出來說一下呢?原因是在lambda表示式中傳遞引數還有一些限制,主要有以下幾點:
引數列表中不能有預設引數
不支援可變引數
所有引數必須有引數名
常用舉例:
(x)+6; }(5);
std::cout
<< "m:"
<< m << std::endl; //輸出m:16
std::cout
<< "n:"
<< (int x, int y) (5, 4) << std::endl; //輸出n:9
auto gfunc = (int x) -> function ; };
auto lfunc = gfunc(4);
std::cout
<< lfunc(5) << std::endl;
auto hfunc = (const function& f, int z) ;
auto a = hfunc(gfunc(7), 8);
int a = 111, b = 222;
auto func = [=, &b]()mutable ;
func();
std::cout
<< "a:"
<< a << " b:"
<< b << std::endl;
a = 333;
auto func2 = [=, &a] ;
func2();
auto func3 = (int x) ->function ; };
std::function f_display_42 = (int x) ;
f_display_42(44);
}
lambda表示式 lambda表示式
1.概述 c 11 中的 lambda 表示式用於定義並建立匿名的函式物件,以簡化程式設計工作。lambda 的語法形式如下 函式物件引數 操作符過載函式引數 mutable 或 exception 宣告 返回值型別可以看到,lambda 主要分為五個部分 函式物件引數 操作符過載函式引數 muta...
Lambda表示式(一)
是什麼 為什麼要用 怎麼用?語法 答 lambda表示式是具有引數和主體的未命名函式。lambda表示式主體可以是block語句或表示式。lambda表示式使我們能夠以緊湊的方式傳遞邏輯。使用lambda表示式的一般語法是 parameters 分隔引數和lambda表示式主體。引數用括號括起來,這...
Lambda表示式和Lambda表示式樹
原版來自 linq學習筆記之二 lambda表示式和lambda表示式樹 lambda 表示式 lambda expressions 是linq實現的另一特性。lambda表示式的作用就是使用使用函式式語法,將方法實現關聯到委託例項。在使用查詢表示式 query expressions 時,查詢表示...