目录
lambda表达式完整的书写格式: [ capture - list ] ( parameters ) mutable -> return-type { statement }
①在C++98中,如果想要对一个数据集合中的元素进行排序,可以使用std::sort方法
- #include
- #include
-
- int main()
- {
- int array[] = {4,1,8,5,3,7,0,9,2,6};
-
- // 默认按照小于比较,排出来结果是升序
- std::sort(array, array+sizeof(array)/sizeof(array[0]));
-
- // 如果需要降序,需要改变元素的比较规则
- std::sort(array, array + sizeof(array) / sizeof(array[0]), greater<int>());
-
- return 0;
- }
②如果待排序元素为自定义类型,需要用户定义排序时的比较规则,这里传入仿函数来指定排序时的比较方式
- struct Goods
- {
- string _name; //名字
- double _price; //价格
- int _evaluate; //评价
- };
-
- struct ComparePriceLess
- {
- bool operator()(const Goods& g1, const Goods& g2)
- {
- return g1._price < g2._price;
- }
- };
-
- struct ComparePriceGreater
- {
- bool operator()(const Goods& g1, const Goods& g2)
- {
- return g1._price > g2._price;
- }
- };
-
- struct CompareEvaluateLess
- {
- bool operator()(const Goods& g1, const Goods& g2)
- {
- return g1._evaluate < g2._evaluate;
- }
- };
-
- struct CompareEvaluateGreater
- {
- bool operator()(const Goods& g1, const Goods& g2)
- {
- return g1._evaluate > g2._evaluate;
- }
- };
-
- int main()
- {
- vector
v = { { "苹果", 2.1, 4.9 }, { "香蕉", 3.3, 5.5 }, { "橙子", 2.2, 6.0 }, { "菠萝", 1.5, 3.6 } }; - sort(v.begin(), v.end(), ComparePriceLess()); //按价格升序排序
- sort(v.begin(), v.end(), ComparePriceGreater()); //按价格降序排序
- sort(v.begin(), v.end(), CompareEvaluateLess()); //按评价升序排序
- sort(v.begin(), v.end(), CompareEvaluateGreater()); //按评价降序排序
- return 0;
- }
③仿函数能够解决这里的问题,但可能仿函数的定义位置可能和使用仿函数的地方隔得比较远,这就要求仿函数的命名必须要通俗易懂,否则会降低代码的可读性
- int main()
- {
- vector
v = { { "苹果", 2.1, 4.9 }, { "香蕉", 3.3, 5.5 }, { "橙子", 2.2, 6.0 }, { "菠萝", 1.5, 3.6} }; -
- sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) { return g1._price < g2._price; }); //按价格升序排序
-
- sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) { return g1._price > g2._price; }); //按价格降序排序
-
- sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) { return g1._evaluate < g2._evaluate; }); //按评价升序排序
-
- sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) { return g1._evaluate < g2._evaluate; }); //按评价降序排序
-
- return 0;
- }
lambda函数的参数列表和返回值类型都是可选部分,但捕捉列表和函数体是不可省略的
- int main()
- {
- []{}; //最简单的lambda表达式,该lambda函数不能做任何事情
- return 0;
- }
①捕获列表描述了上下文中哪些数据可以被lambda函数使用,以及使用的方式是传值还是传引用。
②补充
- void (*PF)();
-
- int main()
- {
- auto f1 = []{cout << "hello world" << endl; };
- auto f2 = []{cout << "hello world" << endl; };
-
- // 此处先不解释原因,等lambda表达式底层实现原理看完后,就清楚了
- //f1 = f2; // 编译失败--->提示找不到operator=()
-
- // 允许使用一个lambda表达式拷贝构造一个新的副本
- auto f3(f2);
- f3();
-
- // 可以将lambda表达式赋值给相同类型的函数指针
- PF = f2;
- PF();
-
- return 0;
- }
- int main()
- {
- int a = 10, b = 20;
- //auto Swap = [](int& x, int& y){}; 简便写法,不必要的可以不写
- auto Swap = [](int& x, int& y)->void{
- int tmp = x;
- x = y;
- y = tmp;
- };
-
- Swap(a, b); //交换a和b
- return 0;
- }
①以引用的方式捕捉所有父作用域中的变量,省略参数列表和返回值类型
- int main()
- {
- int a = 10, b = 20;
- auto Swap = [&]{
- int tmp = a;
- a = b;
- b = tmp;
- };
-
- Swap(); //交换a和b
- return 0;
- }
②只对父作用域中的a、b变量进行捕捉
- int main()
- {
- int a = 10, b = 20;
- auto Swap = [&a, &b]{
- int tmp = a;
- a = b;
- b = tmp;
- };
-
- Swap(); //交换a和b
- return 0;
- }
③实际当我们使用[ & ]或[ = ]的方式捕获变量时,编译器也不一定会把父作用域中所有的变量捕获进来,编译器可能只会对lambda表达式中用到的变量进行捕获,没有必要把用不到的变量也捕获进来,这个主要看编译器的具体实现。
- int main()
- {
- int a = 10, b = 20;
- auto Swap = [a, b]()mutable{
- int tmp = a;
- a = b;
- b = tmp;
- };
-
- Swap(); //交换a和b?
- return 0;
- }
- 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);
-
- // lambda表达式
- auto r2 = [=](double monty, int year)->double { return monty * rate * year; };
- r2(10000, 2);
-
- return 0;
- }
①观察函数对象
②观察lambda表达式
①lambda表达式之间不能相互赋值,即使是两个一模一样的lambda表达式
②所以每个lambda表达式的类型都是不同的,这也就是lambda表达式之间不能相互赋值的原因
③编译器只需要保证每个lambda表达式底层对应类的类名不同即可,并不是每个编译器都会将lambda表达式底层对应类的类名处理成