【C++】C++11 lambda表达式

ゝ一纸荒年。 2022-09-12 05:52 303阅读 0赞

文章目录

  • 0x00 前言
  • 0x01 lambda表达式的概念及声明
    • 1.lambda概念
    • 2.lambda声明
  • 0x02 lambda表达式捕获列表
  • 0x03 lambda表达式实例

0x00 前言

文章中的文字可能存在语法错误以及标点错误,请谅解;

如果在文章中发现代码错误或其它问题请告知,感谢!

0x01 lambda表达式的概念及声明

1.lambda概念

lambda表达式在C++11中被引用,其主要作用是可以不需要为一段逻辑代码而去专门命名一个函数名,并且可以捕获一定范围内的变量,可以方便定义和创建匿名函数,让程序具有更好的可读性和维护性。

2.lambda声明

lambda表达式的语法形式如下:

  1. [capture list] (params list) mutable exception-> return type { function body }

capture list:捕获外部变量列表
params list:形参列表,类似普通函数中的参数
mutable:用来修饰值捕获的外部变量
exception:异常设定
return type:返回类型
function body:函数体

一个lambda表达式举例如下:

  1. auto value = [](int input)->int{ return ++input;};
  2. std::cout << value (1) << std::endl; //输出2

该表达式表示不捕获任何外部变量,只将输入input自加1并返回。

有时候,当lambda返回值很明显可以则可以省略return type

  1. auto value = [](int input){ return ++input;};
  2. std::cout << value (1) << std::endl; //输出2

我们可以省略某些lambda表达式某些部分来实现功能,常见的情况有以下几种:






















常见形式 解释
[capture list] (params list) -> return type {function body;}; 省略了用来修饰值捕获的外部变量,表示声明const类型表达式,不能修改捕获列表中的值
[capture list] (params list) {function body;}; 省略了返回值类型,但编译器可以根据funciton body中的return推断返回值类型,若没有return则返回值类型为void
[capture list] {function body;}; 省略了参数列表,可以看成无参函数

例如当lambda表达式没有形参列表时,可以省略params list,例如:

  1. auto value1 = [](){ return 1;};
  2. auto value2 = []{ return 1;};

0x02 lambda表达式捕获列表

lambda表达式可以通过捕获列表capture list获取指定范围内的变量:
[]:不捕获任何变量。
[&value]按引用捕获 value变量,同时不捕获其他变量。
[=value]按值捕获 value变量,同时不捕获其他变量。
[&]捕获外部作用域中所有变量,并作为引用在函数体function body中使用(按引用捕获)。
[=] 捕获外部作用域中所有变量,并作为副本在函数体function body中使用(按值捕获)。
[=,&value]按值捕获外部作用域中所有变量,并按引用捕获 value变量。
[this] 捕获当前类中的 this 指针,让 lambda 表达式拥有和当前类成员函数同样的访问权限。如果已经使用了 & 或者 =,就默认添加此选项。捕获 this 的目的是可以在 lamda 中使用当前类的成员函数和成员变量。

举例:
例1:引用捕获

  1. #include<iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. int value = 123;
  6. auto f = [&value] { cout << value << endl; };
  7. value = 321;
  8. f();
  9. }

结果:

  1. 321

例2:值捕获

  1. #include<iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. int value = 123;
  6. auto f = [=value] { cout << value << endl; };
  7. value = 321;
  8. f();
  9. }

结果:

  1. 123

在这个例子中,lambda表达式按值捕获了所有外部变量,在捕获一瞬间,value的值就已经被复制到f中,之后value被修改,但是f中存储的值value仍然还是捕获时的值,因此结果输出时123。

例3:修改捕获变量

  1. #include<iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. int value = 123;
  6. //auto f1 = [=](){ cout << ++value << endl; }; //报错,修改按值捕获的外部变量
  7. auto f2 = [=]()mutable { cout << ++value << endl; };
  8. f2();
  9. }

结果:

  1. 124

例4:隐式捕获

  1. #include<iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. int value = 123;
  6. auto f1 = [=] { cout << value << endl; };
  7. auto f2 = [&] { cout << value << endl; };
  8. value = 321;
  9. f1();
  10. f2();
  11. }

结果:

  1. 123
  2. 321

例2例3中值捕获或引用捕获都需要确定需要捕获的变量,我们还可以让编译器根据函数体中的代码推断需要捕获哪些变量,该方式称为隐式捕获,[=]表示按值捕获方式捕获外部变量,[&]表示按引用捕获方式捕获外部变量。

0x03 lambda表达式实例

例5:从小到大排列

  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4. using namespace std;
  5. bool cmp(int a, int b)
  6. {
  7. return a < b;
  8. }
  9. int main()
  10. {
  11. vector<int> vec{ 3, 2, 5, 7, 3, 2 };
  12. vector<int> lambdavec(vec);
  13. sort(vec.begin(), vec.end(), cmp);
  14. cout << "common:" << endl;
  15. for (int it : vec)
  16. cout << it << ' ';
  17. cout << endl;
  18. sort(lambdavec.begin(), lambdavec.end(), [](int a, int b) -> bool { return a < b; }); // Lambda表达式
  19. cout << "lambda:" << endl;
  20. for (int it : lambdavec)
  21. cout << it << ' ';
  22. }

结果:

  1. common:
  2. 2 2 3 3 5 7
  3. lambda:
  4. 2 2 3 3 5 7

以上。
参考文档:
1.http://c.biancheng.net/view/3741.html
2.https://www.cnblogs.com/DswCnblog/p/5629165.html

发表评论

表情:
评论列表 (有 0 条评论,303人围观)

还没有评论,来说两句吧...

相关阅读

    相关 C++ 11 Lambda表达式

    C++ 11中的Lambda表达式用于定义并创建匿名的函数对象,以简化编程工作。Lambda的语法形式如下:               \[函数对象参数\] (操作符重载

    相关 C++ 11 Lambda表达式

       C++ 11中的Lambda表达式用于定义并创建匿名的函数对象,以简化编程工作。Lambda的语法形式如下:               \[函数对象参数\] (操作