利用Lambda表達式,可以方便的定義和創建匿名函數。
聲明Lambda表達式
Lambda表達式完整的聲明格式如下:
[capture list] (params list) mutable exception-> return type { function body }
各項具體含義如下:
- capture list:捕獲外部變量列表
- params list:形參列表
- mutable指示符:用來說用是否可以修改捕獲的變量
- exception:異常設定
- return type:返回類型
- function body:函數體
此外,我們還可以省略其中的某些成分來聲明“不完整”的Lambda表達式,常見的有以下幾種:
序號 | 格式 |
---|---|
1 | [capture list] (params list) -> return type {function body} |
2 | [capture list] (params list) {function body} |
3 | [capture list] {function body} |
其中:
- 格式1聲明了const類型的表達式,這種類型的表達式不能修改捕獲列表中的值。
- 格式2省略了返回值類型,但編譯器可以根據以下規則推斷出Lambda表達式的返回類型:(1):如果function body中存在return語句,則該Lambda表達式的返回類型由return語句的返回類型確定; (2):如果function body中沒有return語句,則返回值為void類型。
-
格式3中省略了參數列表,類似普通函數中的無參函數。
下面的實例說明了Lambda的一個作用:
1 #include <iostream> 2 #include <vector> 3 #include <string> 4 #include <algorithm> 5 #include <fstream> 6 using namespace std; 7 8 bool isShoter(const string &str1, const string &str2)//要改寫的函數 9 { 10 return str1.size() < str2.size(); 11 } 12 13 void outputWords(vector<string> &v) 14 { 15 for (auto it = v.cbegin(); it != v.cend(); ++it) 16 cout << *it << " "; 17 cout << endl; 18 } 19 20 void elimDups(vector<string> &v) 21 { 22 outputWords(v); 23 24 sort(v.begin(), v.end(), isShoter); 25 outputWords(v); 26 27 auto endUnique = unique(v.begin(), v.end()); 28 outputWords(v); 29 30 v.erase(endUnique, v.end()); 31 outputWords(v); 32 } 33 34 int main(int argc, char *argv[]) 35 { 36 ifstream in(argv[1]); 37 if (!in) 38 { 39 cout << "打開文件夾失敗!" << endl; 40 exit(1); 41 } 42 43 vector<string> words; 44 string word; 45 while (in >> word) 46 words.push_back(word); 47 elimDups(words); 48 49 return 0; 50 }
將isShorter函數改為Lambda表達式形式:
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <string> 5 #include <fstream> 6 7 using namespace std; 8 9 void outputWords(vector<string> &v) 10 { 11 for_each(v.cbegin(), v.cend(), [](string &str) { cout << str << ' '; }); 12 cout << endl; 13 } 14 15 void elimDups(vector<string> &v) 16 { 17 outputWords(v); 18 sort(v.begin(), v.end()); 19 outputWords(v); 20 21 auto endUnique = unique(v.begin(), v.end()); 22 outputWords(v); 23 v.erase(endUnique, v.end()); 24 } 25 26 void biggies(vector<string> &v, size_t sz) 27 { 28 elimDups(v); 29 stable_sort(v.begin(), v.end(), [](const string &a, const string &b) { return a.size() < b.size(); });//替換isShorter函數 30 31 auto wc = find_if(v.begin(), v.end(), [sz](const string &s) { return s.size() >= sz; });//另一個Lambda表達式 32 auto count = v.end() - wc; 33 for_each(wc, v.end(), [](const string &s) { cout << s << ' '; }); 34 cout << endl; 35 } 36 37 int main(int argc, char *argv[]) 38 { 39 ifstream in(argv[1]); 40 if (!in) 41 { 42 cout << "打開文件夾失敗!" << endl; 43 exit(1); 44 } 45 46 vector<string> words; 47 string word; 48 while (in >> word) 49 words.push_back(word); 50 biggies(words); 51 52 return 0; 53 }
在C++11之前,我們使用STL的sort函數,需要提供一個謂詞函數。如果使用C++11的Lambda表達式,我們只需要傳入一個匿名函數即可,方便簡潔。