有几天没写了 最近有点小忙 问题不大
7.1 lambda表达式语法
cppauto SendCmd = [&](uint8_t cmd)->bool { CBinary binTemp = binCmd; binTemp.Append(byteVaule).Append(cmd); CBinary binRecv; if (!SendCheck(binRecv, binTemp)) { return false; } return true; }; //lambda 就是函数 一般我用于在函数内部有重复代码时使用 可以提高代码简洁性 [] 这个是捕获列表 &全部捕获 可以到lambda内部使用变量 () 传入参数 -> 传出的值的类型 (这个可以不用了 有auto) {} 里边写函数
7.2 捕获列表
好像有点复杂 分开来写
7.2.1 作用域
[ ] 中得是局部变量 (静态变量可以直接使用)所以
如果将一个lambda表达式定义在全局作用域,那么lambda表达式的捕获列表必须为空。(应该没有人会这么写 )
[ x,y] ===不加&就是只读的捕获 不能对x和y修改
[&x,&y] >> 引用捕获 可读可写
捕获的变量默认为常量,或者说lambda是一个常量函数(类似于常量成员函数)
cppvoid bar3() { int x = 5, y = 8; auto foo = [x, y]() mutable { x += 1; y += 2; return x * y; }; std::cout << foo() << std::endl; }//这个样子可以修改内部的值 但还是值传递 外部的x y 不改变 //与&传递有本质区别 语法规定lambda表达式如果存在说明符,那么形参列表不能省略
7.2.2 捕获值和捕获引用
cpp#include <iostream> int main() { int x = 5, y = 8; auto foo = [x, &y]() mutable { x += 1; y += 2; std::cout << "lambda x = " << x << ", y = " << y << std::endl; return x * y; }; foo(); std::cout << "call1 x = " << x << ", y = " << y << std::endl; foo(); std::cout << "call2 x = " << x << ", y = " << y << std::endl; } 输出结果 lambda []非&传递只传递一次 后面再调用还是这个被lambda修改的值 lambda x = 6, y = 10 call1 x = 5, y = 10 lambda x = 7, y = 12 //这里 是按照6来 再加1得到7 call2 x = 5, y = 12
捕获值的变量在lambda表达式定义的时候已经固定下来了,无论函数在lambda表达式定义后如何修改外部变量的值,lambda表达式捕获的值都不会变化,
cpp#include <iostream> int main() { int x = 5, y = 8; auto foo = [x, &y]() mutable { x += 1; y += 2; std::cout << "lambda x = " << x << ", y = " << y << std::endl; return x * y; }; x = 9; y = 20; foo(); } 结果 lambda x = 6, y = 22
7.2.3 特殊的捕获方法
1.[this] ------ 捕获this指针,捕获this指针可以让我们使用this类型的成员变量和函数。
2.[=] ------ 捕获lambda表达式定义作用域的全部变量的值,包括this。
3.[&] ------ 捕获lambda表达式定义作用域的全部变量的引用,包括this。
7.3 lambda表达式的实现原理
lambda表达式与函数对象差不多
lambda表达式在编译期会由编译器自动生成一个闭包类,在运行时由这个闭包类产生一个对象,我们称它为闭包。在C++中,所谓的闭包可以简单地理解为一个匿名且可以包含定义时作用域上下文的函数对象。现在让我们抛开这些概念,观察lambda表达式究竟是什么样子的
7.4 无状态lambda表达式
C++标准对于无状态的lambda表达式有着特殊的照顾,即它可以隐式转换为函数指针
cppvoid f(void(*)()) {} void g() { f([] {}); } // 编译成功 在上面的代码中,lambda表达式[] {}隐式转换为void(*)()类型 的函数指针。同样,看下面的代码: void f(void(&)()) {} void g() { f(*[] {}); }
这段代码也可以顺利地通过编译。我们经常会在STL的代码中遇到lambda表达式的这种应用。
7.5 在STL中使用lambda表达式
cppstd::vector<int> vec = {5, 2, 9, 1, 5, 6}; // 使用lambda表达式进行排序 std::sort(vec.begin(), vec.end(), [](int a, int b) { return a < b; // 按升序排序 }); std::for_each(vec.begin(), vec.end(), [](int num) { std::cout << num << " "; });
7.6 广义捕获
这个待定
7.7 泛型lambda表达式
cppint main() { auto foo = [](auto a) { return a; }; int three = foo(3); char const* hello = foo("hello"); }
7.8 常量lambda表达式和捕获*this
同7.6待定
7.9 捕获[=, this]
在C++20标准中,又对lambda表达式进行了小幅修改。这一次修改没有加强lambda表达式的能力,而是让this指针的相关语义更加明确。我们知道[=]可以捕获this指针,相似的,[=,*this]会捕获this对象的副本。但是在代码中大量出现[=]和[=,*this]的时候我们可能很容易忘记前者与后者的区别。为了解决这个问题,在C++20标准中引入了[=, this]捕获this指针的语法,它实际上表达的意思和[=]相同,目的是让程序员们区分它与[=,*this]的不同: