赞
踩
目录
lambda表达式就是定义了一个可调用的匿名函数,一般在局部。
[]{}是最简单的lambda表达式,但是该lambda表达式没有任何意义
[capture-list] (parameters) mutable -> return-type { statement }
捕捉列表 参数 去const(单词意思易变的) 返回值 函数体
auto Add1 = [ ](int x, int y)->int {return (x + y); };
- int a = 0, b = 200;
- // [capture-list] (parameters) mutable -> return-type { statement }
- // 捕捉列表 参数 返回值 函数体
-
- // 一般是局部匿名函数 也可以写到全局
- auto Add1 = [](int x, int y)->double {return (x + y) / 3.0; };
- auto Add2 = [](int x, int y)->int {return (x + y) / 3.0; };//传参写法
- auto Add3 = [a, b] {return (a + b) / 3.0; };//捕捉变量写法
-
- cout << Add1(a, b) << endl;
- cout << Add2(a, b) << endl;
- cout << Add3() << endl;
3,4,5,6是几种捕捉方式
- 1. auto Swap1 = [](int& x, int& y){
- int tmp = x;
- x = y;
- y = tmp;
- };
-
- Swap1(a, b);
- cout << a << " " << b << endl;
-
- 2. mutable 只是让传值捕捉变量const属性去掉了,但是捕捉的a,b仍是拷贝,外部的a,b无法被修改
- /*auto Swap2 = [a, b]()mutable{
- int tmp = a;
- a = b;
- b = tmp;
- };*/
-
- 用引用的方式捕捉:
- auto Swap2 = [&a, &b]{
- int tmp = a;
- a = b;
- b = tmp;
- };
-
- Swap2();
- cout << a << " " << b << endl;
-
- 3. int c =2, d=3, e=4, f=5, g=6, ret;
- 传值捕捉全部对象
- auto Func1 = [=]{
- return c + d*e / f + g;
- };
-
- cout << Func1() << endl;
-
- 4. 传引用捕捉全部对象
- auto Func2 = [&]{
- ret = c + d*e / f + g;
- };
-
- Func2();
- cout << ret << endl;
-
- 5. 混着捕捉
- auto Func3 = [c, d, &ret]{
- ret = c + d;
- };
-
- Func3();
- cout << ret << endl;
-
- 6. ret传引用捕捉 其他全部传值捕捉
- auto Func4 = [=, &ret]{
- ret = c + d*e / f + g;
- //c = 1;
- };
-
- Func4();
- cout << ret << endl;

(greater是排降序,less是排升序)
比如:仿函数 sort(v.begin(), v.end(), ComparePriceLess()); 可以写成sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2){return g1._price < g2._price; });
- struct Goods
- {
- string _name; // 名字
- double _price; // 价格
- int _evaluate; // 评价
-
- Goods(const char* str, double price, int evaluate)
- :_name(str)
- , _price(price)
- , _evaluate(evaluate)
- {}
- };
-
- struct Compare1
- {
- bool operator()(const Goods& gl, const Goods& gr)
- {
- return gl._evaluate < gr._evaluate;
- }
- };
-
- struct ComparePriceLess
- {
- bool operator()(const Goods& gl, const Goods& gr)
- {
- return gl._price < gr._price;
- }
- };
-
- struct ComparePriceGreater
- {
- bool operator()(const Goods& gl, const Goods& gr)
- {
- return gl._price > gr._price;
- }
- };
-
- int main()
- {
-
- vector<Goods> v = { Goods( "苹果", 2.1, 5 ), { "香蕉", 3, 4 }, { "橙子", 2.2, 3 }, { "菠萝", 1.5, 4 } };
-
- //sort(v.begin(), v.end()); 自定义类型没重载<不能用less或者greater
- 1.正常用仿函数写sort:
- sort(v.begin(), v.end(), Compare1());
- sort(v.begin(), v.end(), ComparePriceLess());
- sort(v.begin(), v.end(), ComparePriceGreater());
- 2.用lambda代替仿函数:
- (1)常规写法
- auto com1 = [](const Goods& g1, const Goods& g2){return g1._price < g2._price; };
- sort(v.begin(), v.end(), com1);
-
- (2)匿名对象写法
- sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2){
- return g1._price < g2._price; });
-
- cout << endl;
-
- sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2){
- return g1._price > g2._price; });
-
- cout << endl;
-
- sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2){
- return g1._evaluate < g2._evaluate; });
-
- cout << endl;
-
- sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2){
- return g1._evaluate > g2._evaluate; });
-
- cout << endl;
-
- return 0;
- }

但是允许使用lambda表达式拷贝构造
也可以将lambda表达式赋值给相同类型的函数指针,了解一下,一般不建议这么用,意义不大
- void (*PF)();
- int main()
- {
- auto f1 = [] {cout << "hello world" << endl; };
- auto f2 = [] {cout << "hello world" << endl; };
-
- f1 = f2; //错误,lambda对象之间不能相互赋值,编译失败--->提示找不到operator=()
-
- auto f3(f2); //正确,允许使用一个lambda表达式拷贝构造一个新的副本
- f3();
- // 可以将lambda表达式赋值给相同类型的函数指针,了解一下,一般不建议这么用
- PF = f2; //上面有void (*PF)(); PF和f2都是无类型无返回值
- PF();
- return 0;
- }
lambda表达式底层是一个仿函数。每个lambda都会被转换成一个仿函数类型,仿函数类名称lambda+ uuid。uuid是生成的随机不同的字符串,防止冲突
- class Rate
- {
- public:
- Rate(double rate) : _rate(rate)
- {}
- double operator()(double money, int year)
- {
- return money * _rate * year;
- }
- private:
- double _rate;
- };
- int main()
- {
- // 函数对象
- double rate = 0.49;
- Rate r1(rate);
- r1(10000, 2);
- // lamber
- auto r2 = [=](double monty, int year)->double {return monty * rate * year;};
- r2(10000, 2);
- return 0;
- }

仿函数:函数对象,又称为仿函数,即可以像函数一样使用的对象,就是在类中重载了operator()运算符的类对象。
r1就是仿函数,这里调用的是重载的了operator()运算符。lambda底层则是被转换成了一个 类名称叫lambda+ uuid 的仿函数,r2(10000, 2);就是调用了此仿函数的operator()运算符
1、函数指针
2、仿函数对象
3、lambda
- template<class F, class T>
- T useF(F f, T x)
- {
- static int count = 0;
- cout << "count:" << ++count << endl;
- cout << "count:" << &count << endl;
-
- return f(x);
- }
-
- double f(double i)
- {
- return i / 2;
- }
-
- struct Functor
- {
- double operator()(double d)
- {
- return d / 3;
- }
- };
-
- int main()
- {
- // 函数名
- cout << useF(f, 11.11) << endl;
-
- // 函数对象
- cout << useF(Functor(), 11.11) << endl;
-
- // lamber表达式
- cout << useF([](double d)->double{ return d / 4; }, 11.11) << endl;
-
- return 0;
- }

通过上面的程序验证,我们会发现useF函数模板实例化了三份。
把对应的可调函数 函数指针/仿函数/lambda 包装起来使用,比如包装lambda:
- std::function<int(int, int)> func5 = [](int a, int b) {return a + b; }; ——包装
- cout << func5(100, 200) << endl; ——包装以后直接使用
包装器用途:统一类型,
std::function<int(int, int)> func1 = f;
第一个int是被调用函数的返回类型,小括号俩int是被调用函数的形参类型,f是要包的那个函数。
template <class Ret, class... Args>
- int f(int a, int b)
- {
- return a + b;
- }
-
- struct Functor
- {
- public:
- int operator() (int a, int b)
- {
- return a + b;
- }
- };
-
- class Plus
- {
- public:
- static int plusi(int a, int b)
- {
- return a + b;
- }
-
- double plusd(double a, double b)
- {
- return a + b;
- }
- };
-
- int main()
- {
- std::function<int(int, int)> func1 = f;
- cout << func1(1, 2) << endl;
-
- std::function<int(int, int)> func2 = Functor();
- cout << func2(10, 20) << endl;
-
- 静态成员函数包装可以加&也可以不加(建议都加&)
- std::function<int(int, int)> func3 = &Plus::plusi;
- cout << func3(100, 200) << endl;
-
- 规定:非静态成员函数包装必须加&,因为有this指针,所以参数多传一个域
- std::function<double(Plus, double, double)> func4 = &Plus::plusd;
- cout << func4(Plus(), 100.11, 200.11) << endl;//Plus()是匿名对象,有对象才能调函数
-
- std::function<int(int, int)> func5 = [](int a, int b) {return a + b; };
- cout << func5(100, 200) << endl;
-
- return 0;
- }

解决:包装器,把函数/仿函数/lambda表达式 包装成一个类型,只实例化一份
-
- #include <functional>
-
- template<class F, class T>
- T useF(F f, T x)
- {
- static int count = 0;
- cout << "count:" << ++count << endl;
- cout << "count:" << &count << endl;
-
- return f(x);
- }
-
- double f(double i)
- {
- return i / 2;
- }
-
- struct Functor
- {
- double operator()(double d)
- {
- return d / 3;
- }
- };
-
- int main()
- {
- // 函数名
- std::function<double(double)> func1 = f;
- cout << useF(func1, 11.11) << endl;
-
- // 函数对象
- std::function<double(double)> func2 = Functor();
- cout << useF(func2, 11.11) << endl;
-
- // lamber表达式
- std::function<double(double)> func3 = [](double d)->double{ return d / 4; };
- cout << useF(func3, 11.11) << endl;
-
- return 0;
- }

例如:
["4","13","5","/","+"] ,把4,13,5入栈,取到“/”后,13/5=2,2入栈,栈里有:4,2;取到 “+” 后,4+2=6,结果为6
- class Solution {
- public:
- int evalRPN(vector<string>& tokens) {
- stack<long long> st;
- map<string,std::function<long long(long long,long long)>> opFuncMap={
- {"+",[](long long a,long long b){return a+b;}},
- {"-",[](long long a,long long b){return a-b;}},
- {"*",[](long long a,long long b){return a*b;}},
- {"/",[](long long a,long long b){return a/b;}}
- };
- for(auto& e: tokens)
- {
- if(opFuncMap.count(e))
- {
- int right=st.top();
- st.pop();
- int left=st.top();
- st.pop();
- st.push(opFuncMap[e](left,right));
- }
- else
- {
- st.push(stoll(e));
- }
- }
- return st.top();
- }
- };

作用:调整可调用对象参数的个数和顺序
fn是可调用对象,Args&&... args是参数包
(可调用类型对象:1、函数指针 2、仿函数对象 3、lambda)
正常情况下面都是传两个参数:
- int f(int a, int b)
- {
- return a - b;
- }
-
- struct Functor
- {
- public:
- int operator() (int a, int b)
- {
- return a + b;
- }
- };
-
-
- class Plus
- {
- public:
- Plus(int x = 2)
- :_x(x)
- {}
-
- int plusi(int a, int b)
- {
- return (a + b)*_x;
- }
- private:
- int _x;
- };
-
- int main()
- std::function<int(int, int)> func1 = f;
- cout << func1(1, 2) << endl;
-
- std::function<int(int, int)> func2 = Functor();
- cout << func2(10, 20) << endl;

- // 3个参数
- std::function<int(Plus, int, int)> func3 = &Plus::plusi;
- cout << func3(Plus(), 100, 200) << endl;
就导致定义map时,map的second类型是两个参数的包装器,则这3个参数的传不进去,只能通过bind解决:
- map<string, std::function<int(int, int)>> opFuncMap =
- {
- { "普通函数指针", f },
- { "函数对象", Functor() },
- { "成员函数指针", std::bind(&Plus::plusi, Plus(10), placeholders::_1, placeholders::_2) }
- };
改成传2个参数的:
2个参数 这里相当于绑定了第一个参数10;1个参数 这里相当于绑定了第一个参数为10,第二个参数为30;
- // 2个参数
- std::function<int(int, int)> func4 = std::bind(&Plus::plusi, Plus(10), placeholders::_1, placeholders::_2);
- cout << func4(10,20) << endl;
-
- 如果用bind改成传一个参数的:
- // 1个参数
- std::function<int(int)> func5 = std::bind(&Plus::plusi, Plus(10),
- 30, placeholders::_1);
-
- cout << func5(200) << endl;
此时66传给_1,77传给_2,f函数中a接收_2的77,b接收_2的66
-
- int f(int a, int b)
- {
- return a - b;
- }
-
- int main()
- {
- 未调整:
- std::function<int(int, int)> func1 = f;
- cout << func1(66, 77) << endl;
- 调整顺序:
- // 调整顺序 -- 用处不大
- std::function<int(int, int)> func6 = std::bind(f, placeholders::_2,
- placeholders::_1);
- cout << func6(66, 77) << endl;
- }

- int f(int a, int b)
- {
- return a - b;
- }
-
- struct Functor
- {
- public:
- int operator() (int a, int b)
- {
- return a + b;
- }
- };
-
-
- class Plus
- {
- public:
- Plus(int x = 2)
- :_x(x)
- {}
-
- int plusi(int a, int b)
- {
- return (a + b)*_x;
- }
- private:
- int _x;
- };
-
- int main()
- {
- std::function<int(int, int)> func1 = f;
- cout << func1(1, 2) << endl;
-
- std::function<int(int, int)> func2 = Functor();
- cout << func2(10, 20) << endl;
-
- // 3个参数
- std::function<int(Plus, int, int)> func3 = &Plus::plusi;
- cout << func3(Plus(), 100, 200) << endl;
-
- // 调整可调用对象的参数个数和顺序
- // _1 _2 _3... 表示你要自己传的那些参数,_1表示第一个参数传给_1
- // 调整个数
- // 2个参数
- std::function<int(int, int)> func4 = std::bind(&Plus::plusi, Plus(10),
- placeholders::_1, placeholders::_2);
-
- // 1个参数
- std::function<int(int)> func5 = std::bind(&Plus::plusi, Plus(10),
- 10, placeholders::_1);
-
- cout << func5(200) << endl;
-
- // 调整顺序 -- 用处不大
- std::function<int(int, int)> func6 = std::bind(f, placeholders::_2,
- placeholders::_1);
- cout << func1(66, 77) << endl;
- cout << func6(66, 77) << endl;
-
- map<string, std::function<int(int, int)>> opFuncMap =
- {
- { "普通函数指针", f },
- { "函数对象", Functor() },
- { "成员函数指针", std::bind(&Plus::plusi, Plus(10), placeholders::_1, placeholders::_2) }
- };
-
- cout << opFuncMap["普通函数指针"](1, 2) << endl;
- cout << opFuncMap["函数对象"](1, 2) << endl;
- cout << opFuncMap["成员函数指针"](1, 2) << endl;
-
-
- return 0;
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。