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(); } void elimDups(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; }