目录
-
- lambda
-
- 1、什么是lambda
- 2、lambda的结构
-
- 2.1、捕获列表(capture)
- 2.2、参数列表(parameters)
- 2.3、可变规则(mutable)
- [2.4、 异常说明(noexcept)](#2.4、 异常说明(noexcept))
- 2.5、指定返回类型(return_type)
- 结语
lambda
1、什么是lambda
lambda 表达式 是 C++11 引入的一种语法,让你可以在代码中直接定义一个"匿名函数",不需要写函数名。
示例demo
cpp
#include <iostream>
#include <cstdio>
int main()
{
auto add = [](int a, int b) -> int
{
return a + b;
};
printf("add : %d\n", add(3, 4));
return 0;
}
2、lambda的结构
cpp
[capture](parameters) mutable noexcept -> return_type {
// 函数体
}
capture : 捕获列表
parameters : 参数列表
mutable : 可变规则
noexcept : 异常说明
return_type : 指定返回类型
{} : 函数体
2.1、捕获列表(capture)
捕获列表一共有下述五种类型
捕获方式 | 写法 | 含义 |
---|---|---|
值捕获 | [x] |
拷贝外部变量 x 的值 |
引用捕获 | [&x] |
按引用使用外部变量 x |
全部值捕获 | [=] |
拷贝父作用域所有外部变量 |
全部引用捕获 | [&] |
引用父作用域所有外部变量 |
混合捕获 | [=, &y] / [&, x] |
大部分按某种方式捕获,个别特殊指定 |
值捕获[x]
cpp
#include <iostream>
#include <cstdio>
int main()
{
int a = 1;
auto GetPrama = [a](){
printf("a : %d\n", a);
};
GetPrama();
return 0;
}
1、此方式不能在lambda表达式内部改变捕获变量的数值, 也可以理解为传入的参数a是const类型的变量,因此 无法在函数体内修改。
2、此方式还可以捕获this
cpp
#include <iostream>
#include <cstdio>
class TestLambda
{
public:
TestLambda() = default;
~TestLambda() = default;
TestLambda(const TestLambda &other) = delete;
TestLambda& operator=(const TestLambda &other) = delete;
TestLambda(TestLambda &&other) = delete;
TestLambda& operator=(TestLambda &&other) = delete;
public:
void LambadFunc()
{
auto func = [this](){
this->Print();
};
func();
}
private:
void Print()
{
printf("i am : %s\n", __FUNCTION__);
}
};
int main()
{
TestLambda t;
t.LambadFunc();
return 0;
}
3、如果**[]**中什么也不写,则不捕获任何东西。
引用捕获[&x]
在值捕获 的例子中我们的a无法在lambda的函数体中改变,如使用引用捕获则可以改变
cpp
#include <iostream>
#include <cstdio>
int main()
{
int a = 1;
auto GetPrama = [&a](){
a = 6;
return a;
};
printf("a : %d\n", GetPrama());
return 0;
}
ps:此方式也适用于引用捕获this
全部值捕获[=]
cpp
#include <iostream>
#include <cstdio>
int main()
{
int a = 1, b = 2, c = 3;
auto GetPrama = [=]()
{
printf("a : %d, b : %d, c : %d\n", a, b, c);
};
GetPrama();
return 0;
}
全部引用捕获[&]
cpp
#include <iostream>
#include <cstdio>
#include <functional>
int main()
{
int a = 1, b = 2, c = 3;
std::function<void(void)> GetPrama = [&]()
{
a = 6;
b = 6;
c = 6;
};
GetPrama();
printf("a : %d, b : %d, c : %d\n", a, b, c);
return 0;
}
混合捕获
cpp
#include <iostream>
#include <cstdio>
#include <functional>
int main()
{
int a = 1, b = 2, c = 3;
std::function<void(void)> GetPrama1 = [&, b]() // 全部引用捕获但是b除外, b是值捕获
{
a = 6;
// b = 6; 唯独b是值捕获,因此无法在lambda的函数体中修改。
c = 6;
};
GetPrama1();
printf("a : %d, b : %d, c : %d\n", a, b, c);
// std::function<void(void)> GetPrama2 = [b, &]() //<---b说明是值捕获b,然后&是全部引用捕获。
// { // 混合捕获只支持这两种模式 [=, &y, &z ....] [&, x, y, z ....]
// a = 6;
// b = 6;
// c = 6;
// };
std::function<void(void)> GetPrama3 = [=, &b, &c]() // 全部引用捕获但是b除外, b是值捕获
{
// a = 6; 唯独a是值捕获,因此无法在lambda的函数体中修改。
b = 8;
c = 8;
};
GetPrama3();
printf("a : %d, b : %d, c : %d\n", a, b, c);
return 0;
}
2.2、参数列表(parameters)
参数列表很好理解,就当函数参数一样定义就行
cpp
#include <iostream>
#include <cstdio>
#include <functional>
int main()
{
int a = 1, b = 2, c = 3;
auto GetPrama1 = [a, b](int &x, int &y)
{
x = a;
y = b;
};
int x, y;
GetPrama1(x, y);
printf("x : %d, y : %d\n", x, y);
return 0;
}
2.3、可变规则(mutable)
上面我们说了值捕获无法修改捕获对象的数值,但是使用mutable可以强制捕获,让其在lambda的函数体中可以被改变,但是函数体以外捕获对象的数值是不变得。
cpp
#include <iostream>
#include <cstdio>
#include <functional>
int main()
{
int a = 1, b = 2, c = 3;
auto GetPrama1 = [a]() mutable
{
a = 6;
printf("GetPrama1 a : %d\n", a);
};
GetPrama1();
printf("main a : %d\n", a); //原本a的数不会被改变。
return 0;
}
2.4、 异常说明(noexcept)
这个一般不咋用到,简单点说如果你认为你的函数体内不会抛出异常,你就可以带上这个参数。
cpp
#include <iostream>
#include <cstdio>
#include <functional>
int main()
{
int a = 1;
auto GetPrama1 = [a]() mutable noexcept
{
a = 6;
};
GetPrama1();
printf("a : %d\n", a);
return 0;
}
2.5、指定返回类型(return_type)
lambda默认推导出返回值类型,也可以显式指定返回值的类型。
cpp
#include <iostream>
#include <cstdio>
#include <functional>
int main()
{
auto GetPrama = []() mutable noexcept -> double
{
int a = 6, b = 2;
return static_cast<double>(a/b);
};
printf("val : %f\n", GetPrama());
return 0;
}
结语
感谢您的阅读,如有问题可以私信或评论区交流。
^ _ ^