10.3 Customizing Operations(自定義操作)
10.3.2 Lambda Expression(匿名函式)
#include <iostream> #include <algorithm> #include <vector> #include <string> #include <numeric> using namespace std; bool isShorter(const string &s1, const string &s2) { return s1.size() < s2.size(); } voidelimDups(vector<string> &word) { stable_sort(word.begin(), word.end(), isShorter); //字元大小從小到大排序 auto end_unique = unique(word.begin(), word.end()); word.erase(end_unique, word.end()); } int main() { vector<string> vec = { "hello", "ni", "aui", "ni", "wup", "hello", "ni" }; elimDups(vec); for (auto &i : vec) { cout << i << " "; } system("PAUSE"); return 0; }
Like find the find_if algorithm takes a pair of iterators denoting a rang.Unlike the find ,the third argument to find_if is a predicate.The find_if algorithm calls the given predicate on each element in the input range.It returns the first element for which the predicate returns a nonzero vaule, or its end iterator if no such element is found.
[capture list](parameter list) -> return type { function body }
我們能夠省略形參列表和返回型別之一或者全部,但必須包含獲取列表和函式主體。
#include <iostream> #include <algorithm> using std::cout; using std::endl; int main() { auto f = [] { return 66; }; cout << f() << endl; system("PAUSE"); return 0; }
在一個匿名函式中,省略圓括號和引數列表,等同於指定一個空參列表。
改編開頭的例子:
#include <iostream> #include <algorithm> #include <vector> #include <string> #include <numeric> using namespace std; void elimDups(vector<string> &word) { stable_sort(word.begin(), word.end(), [](const string &s1, const string &s2)-> bool{ return s1.size() < s2.size(); }); //字元大小從小到大排序 auto end_unique = unique(word.begin(), word.end()); word.erase(end_unique, word.end()); } int main() { vector<string> vec = { "hello", "ni", "biu", "ni", "qiu", "hello", "ni" }; elimDups(vec); for (auto &i : vec) { cout << i << " "; } cout << endl; system("PAUSE"); return 0; }
#include <iostream> #include <algorithm> #include <vector> #include <string> #include <numeric> using namespace std; void elimDups(vector<string> &word, int sz) { stable_sort(word.begin(), word.end(), [](const string &s1, const string &s2)-> bool{ return s1.size() < s2.size(); }); //字元大小從小到大排序 auto end_unique = unique(word.begin(), word.end()); word.erase(end_unique, word.end()); auto wc = find_if(word.begin(), word.end(), [sz](const string &a) -> bool{ return a.size() >= sz; }); //->bool可以不寫,計算機能夠通過a.size() >= sz;判斷出返回型別 //find_if返回第一個滿足條件元素的迭代器 //如果沒有滿足條件的,複製word.end()給wc if (wc == word.end()) { cout << "no bigger of " << sz << endl; return; } for (auto i = wc; i < word.end();) { cout << *i++ << endl; } } int main() { vector<string> vec = { "hello", "ni", "biu", "ni", "qiu", "hello", "ni" }; elimDups(vec, 3); system("PAUSE"); return 0; }
10.3.3 匿名函式列表獲取和返回
當我們定義一個匿名函式時,編譯器生成對應匿名函式列表的一個新的(未命名)型別。類似於普通函式,但是未命名。
我們能夠通過值獲取或者引用獲取引數列表。
#include <iostream> #include <algorithm> #include <vector> using namespace std; int main() { int a = 9; auto val = [a](int b = 5) { return a + b; }; //值傳遞 cout << val() << endl; //auto val1 = [&a](int b = 5) { return ++a; }; //cout << val1() << endl; auto val2 = [&a](int b = 5) {return a + b; }; //引用傳遞 cout << val2() << endl; a += 2; cout << endl; cout << "值傳遞再次呼叫結果:" << val() << endl; cout << "引用傳遞再次呼叫結果:" << val2() << endl; system("PAUSE"); return 0; }
當我們通過引用獲取值時,我們必須確定這個值在匿名函式執行時存在。
如果可能的話,避免使用指標或者引用獲取值。
&告訴編譯器通過引用獲取值,=告訴編譯器通過值獲取值。
#include <iostream> #include <algorithm> #include <vector> #include <string> using namespace std; void biggist(vector<string> &words, vector<string>::size_type sz, ostream &os = cout, char c = ' ') { auto po = find_if(words.begin(), words.end(), [=](const string &s) {return s.size() >= sz; }); //sz值獲取 cout << "size over or equipment 3:" << *po << endl; for_each(words.begin(), words.end(), [&, c](const string &s) { os << s << c; }); //os引用獲取,c值獲取 cout << endl; for_each(words.begin(), words.end(), [=, &os](const string &s) {os << s << c; }); //os引用獲取,c值獲取 } int main() { vector<string> vec = { "heoo", "hi", "biu", "cps", "heiuwe" }; vector<string>::size_type n = 3; biggist(vec, n); system("PAUSE"); return 0; }
transform演算法和一個匿名函式用絕對值代替一個順序函式中的負值。
#include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { vector<int> vec = { -1, 2, 3, -4, 5, 6 }; transform(vec.begin(), vec.end(), vec.begin(), [](int i) {return i < 0 ? -i : i; }); //編譯能夠通過i < 0?判斷返回型別 transform(vec.begin(), vec.end(), vec.begin(), [](int i) { if (i < 0) return -i; else return i; }); //按照C++11標準,這樣寫error,無法通過i或者-i判斷返回型別,但是編譯器自身優化了,可以輸出 transform(vec.begin(), vec.end(), vec.begin(), [](int i) -> int{ if (i < 0) return -i; else return i; }); //第二種的標準寫法 system("PAUSE"); return 0; }
10.3.4 繫結實參
auto newCallable = bind(callable, arg_list);
bind()在標頭檔案<functional>中
#include <iostream> #include <vector> #include <algorithm> #include <functional> using namespace std; using namespace std::placeholders; bool check_size(const string &a, string::size_type sz) { return a.size() >= sz; } int main() { auto check = bind(check_size, _1, 5); //_1所在位置表示函式引數列表第幾位引數待輸入,1表示check()時傳入的第一個值 string s = "hello"; bool n = check(s); cout << n << endl; system("PAUSE"); return 0; }
#include <iostream> #include <vector> #include <algorithm> #include <functional> #include <string> using namespace std; using namespace std::placeholders; void func(const string &a, const string &b, const string &c, const string &d) { cout << "a:" << a << endl; cout << "b:" << b << endl; cout << "c:" << c << endl; cout << "d:" << d << endl; } int main() { auto f = bind(func, "hello", _2, "liu", _1); //_2所在位置,表示第二個函式引數,2表示第二個獲取值。 //_2所在位置,表示第四個函式引數,1表示第一個獲取值。 f("ran", "ya"); //"ran"給_1, "ya"給_2 system("PAUSE"); return 0; }
因為ostream不能被copy,但我們能夠使用ref函式返回一個物件的引用,引用物件的可以被copy的
#include <iostream> #include <vector> #include <algorithm> #include <functional> #include <string> using namespace std; using namespace std::placeholders; ostream &print(ostream &os, const string &s, char c) { return os << s << c; //s和c的資料流傳送到os中,再return,os輸出物件是螢幕 } int main() { ostream &os = cout; vector<string> vec = { "hello", "ni", "hao" }; //error:for_each(vec.begin(), vec.end(), bind(print, os, _1, ' ')); for_each(vec.begin(), vec.end(), bind(print, ref(os), _1, ' ')); system("PAUSE"); return 0; }