23.C++11(四)
一.lambda表达式
1.C++98中的一个例子
#include <iostream>
#include <vector>
using namespace std;/////////////////////////////////////////////////////////////////////////
#include<algorithm>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._price < gr._price;}
};struct Compare2
{bool operator()(const Goods& gl, const Goods& gr){return gl._price > gr._price;}
};int main()
{vector<Goods> v = { { "苹果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2,
3 }, { "菠萝", 1.5, 4 } };sort(v.begin(), v.end(), Compare1());sort(v.begin(), v.end(), Compare2());return 0;
}
2.lambda表达式
lambda表达式书写格式:[capture-list] (parameters) mutable -> return-type { statement }
我们可以将lambda表达式当成匿名函数
#include <iostream>
#include <vector>
using namespace std;// lambda 匿名函数的对象
int main()
{auto add1 = [](int x, int y)->int {return x + y; };cout << add1(1, 2) << endl;auto func1 = []()->int{cout << "hello ltw" << endl;cout << "hello world" << endl;return 0;};func1();// 返回值类型可自动推导类型,所以可以省略// 无参数可以省略auto func2 = []{cout << "hello ltw" << endl;cout << "hello world" << endl;return 0;};cout << func2() << endl;auto func3 = []{cout << "hello ltw" << endl;cout << "hello world" << endl;};func3();return 0;
}
3.用lambda改造上面的排序
#include <iostream>
#include <vector>
using namespace std;/////////////////////////////////////////////////////////////////////////
#include<algorithm>struct Goods
{string _name; // 名字double _price; // 价格int _evaluate; // 评价//...Goods(const char* str, double price, int evaluate):_name(str), _price(price), _evaluate(evaluate){}
};int main()
{vector<Goods> v = { { "苹果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2,
3 }, { "菠萝", 1.5, 4 } };// 价格升序sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2)->bool{return g1._price < g2._price;});sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2)->bool{return g1._price > g2._price;});sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2)->bool{return g1._evaluate < g2._evaluate;});sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2)->bool{return g1._evaluate > g2._evaluate;});return 0;
}
4.lambda里面的参数
相当于是const修饰过的
刚刚我们的传值捕捉,只是捕捉到了拷贝
5.lambda里面捕捉参数
a.所有传值捕捉
int x = 0;int main()
{// 只能用当前lambda局部域和捕捉的对象和全局对象int a = 0, b = 1, c = 2, d = 3;// 所有值传值捕捉auto func1 = [=]{int ret = a + b + c + d + x;return ret;};return 0;
}
b.所有传引用捕捉
int x = 0;int main()
{// 只能用当前lambda局部域和捕捉的对象和全局对象int a = 0, b = 1, c = 2, d = 3;// 所有值传引用捕捉auto func2 = [&]{a++;b++;c++;d++;int ret = a + b + c + d;return ret;};
}
c.分开进行捕捉
int x = 0;int main()
{// 只能用当前lambda局部域和捕捉的对象和全局对象int a = 0, b = 1, c = 2, d = 3;// 混合捕捉auto func3 = [&a, b]{a++;// b++;int ret = a + b;return ret;};return 0;
}
d.混合捕捉
int x = 0;int main()
{// 只能用当前lambda局部域和捕捉的对象和全局对象int a = 0, b = 1, c = 2, d = 3;// 混合捕捉// 所有值以引用方式捕捉,d用传值捕捉auto func4 = [&, d]{a++;b++;c++;//d++;int ret = a + b + c + d;};return 0;
}
int x = 0;int main()
{// 只能用当前lambda局部域和捕捉的对象和全局对象int a = 0, b = 1, c = 2, d = 3;auto func5 = [=, &d]() mutable{a++;b++;c++;d++;int ret = a + b + c + d;};return 0;
}
6.匿名函数对象
// lambda 匿名函数的对象
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.015;Rate r1(rate);cout << r1(10000, 2) << endl;// lambdaauto r2 = [rate](double monty, int year)->double{return monty * rate * year;};cout << r2(10000, 2) << endl;int x = 1, y = 2;auto r3 = [=](double monty, int year)->double{return monty * rate * year;};cout << r3(10000, 2) << endl;return 0;
}
lambda的底层还是调用我们的operator()
UUID是通过算法实现的一个唯一的字符串
二.function
1.function的使用
在使用的时候,我们要进行包头文件 #include <functional> --> 其他仿函数也在这里面
#include<functional>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()
{// 包装可调用对象function<int(int, int)> f1 = f;function<int(int, int)> f2 = Functor();function<int(int, int)> f3 = [](int a, int b) {return a + b; };cout << f1(1, 1) << endl;cout << f2(1, 1) << endl;cout << f3(1, 1) << endl;
}
https://leetcode.cn/problems/evaluate-reverse-polish-notation/description/
原来的提交代码如下:
class Solution {
public:int evalRPN(vector<string>& tokens) {stack<int> st;int i = 0;for (string token : tokens) {if (token=="+"||token=="-"||token=="*"||token=="/") {int b = st.top();st.pop();int a = st.top();st.pop();if (token == "+") {st.push(a + b);} else if (token == "-") {st.push(a - b);} else if (token == "*") {st.push(a * b);} else if (token == "/") {st.push(a / b);}}else{st.push(stoi(token));}}return st.top();}
};
使用function+lambda进行使用,代码如下:
class Solution {
public:int evalRPN(vector<string>& tokens) {stack<int> st;int i = 0;map<string,function<int(int,int)>> opFuncMap = {{"+",[](int x,int y){return x + y;}},{"-",[](int x,int y){return x - y;}},{"*",[](int x,int y){return x * y;}},{"/",[](int x,int y){return x / y;}}};for (auto& str : tokens) {if (opFuncMap.count(str)) {int right = st.top();st.pop();int left = st.top();st.pop();int ret = opFuncMap[str](left,right);st.push(ret);}else{st.push(stoi(str));}}return st.top();}
};
这样就极大的减少了我们的代码量
function大部分使用在网络那个地方,来了一个命令对应那个函数
还有一点,就是function在进行赋值时,参数必须要进行严格的匹配
2.function包装其他成员函数
#include<functional>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()
{// 包装静态成员函数function<int(int, int)> f4 = &Plus::plusi;cout << f4(1, 1) << endl;// 包装非静态成员函数function<double(Plus*, double, double)> f5 = &Plus::plusd;Plus pd;cout << f5(&pd, 1.1, 1.1) << endl;function<double(Plus, double, double)> f6 = &Plus::plusd;cout << f6(pd, 1.1, 1.1) << endl;cout << f6(Plus(), 1.1, 1.1) << endl;return 0;
}
这两种写法都是可以的:
就是将plusd()存储在f5里面,在使用的时候,将参数传进去
三.bind的使用
1.交换参数位置
placeholders,用_1,_2,_3来代替第一,第二,第三个参数
using placeholders::_1;
using placeholders::_2;
using placeholders::_3;int Sub(int a, int b)
{return (a - b) * 10;
}int main()
{auto sub1 = bind(Sub, _1, _2);cout << sub1(10, 5) << endl;// bind 本质返回的一个仿函数对象// 调整参数顺序(不常用)// _1代表第一个实参// _2代表第二个实参// ...auto sub2 = bind(Sub, _2, _1);cout << sub2(10, 5) << endl;
}
2.修改参数个数
using placeholders::_1;
using placeholders::_2;
using placeholders::_3;int Sub(int a, int b)
{return (a - b) * 10;
}int SubX(int a, int b, int c)
{return (a - b - c) * 10;
}int main()
{// 调整参数个数 (常用)auto sub3 = bind(Sub, 100, _1);cout << sub3(5) << endl;auto sub4 = bind(Sub, _1, 100);cout << sub4(5) << endl;
}
using placeholders::_1;
using placeholders::_2;
using placeholders::_3;int SubX(int a, int b, int c)
{return (a - b - c) * 10;
}int main()
{// 分别绑死第123个参数auto sub5 = bind(SubX, 100, _1, _2);cout << sub5(5, 1) << endl;auto sub6 = bind(SubX, _1, 100, _2);cout << sub6(5, 1) << endl;auto sub7 = bind(SubX, _1, _2, 100);cout << sub7(5, 1) << endl;
}
主要用法:
#include<functional>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;}
};using placeholders::_1;
using placeholders::_2;
using placeholders::_3;int Sub(int a, int b)
{return (a - b) * 10;
}int SubX(int a, int b, int c)
{return (a - b - c) * 10;
}int main()
{function<double(Plus, double, double)> f6 = &Plus::plusd;Plus pd;cout << f6(pd, 1.1, 1.1) << endl;cout << f6(Plus(), 1.1, 1.1) << endl;// bind一般用于,绑死一些固定参数function<double(double, double)> f7 = bind(&Plus::plusd, Plus(), _1, _2);cout << f7(1.1, 1.1) << endl;
}
3.使用
将我们上面的计算利率来使用bind
#include <iostream>
#include <functional>
using namespace std;using placeholders::_1;
using placeholders::_2;
using placeholders::_3;int main()
{//auto func1 = [](double rate, double monty, int year)->double {return monty * rate * year;};auto func1 = [](double rate, double monty, int year)->double {double ret = monty;for (int i = 0; i < year; i++){ret += ret * rate;}return ret - monty;};function<double(double)> func3_1_5 = bind(func1, 0.015, _1, 3);function<double(double)> func5_1_5 = bind(func1, 0.015, _1, 5);function<double(double)> func10_2_5 = bind(func1, 0.025, _1, 10);function<double(double)> func20_3_5 = bind(func1, 0.035, _1, 30);cout << func3_1_5(1000000) << endl;cout << func5_1_5(1000000) << endl;cout << func10_2_5(1000000) << endl;cout << func20_3_5(1000000) << endl;return 0;
}