#include <iostream>
#include <memory> // std::make_unique
#include <utility> // std::move
#include <functional>
/*lambda表达式是匿名函数,本质是一个仿函数(可调用对象)
[捕获列表](参数列表) mutable(可选) 异常属性 -> 返回类型 {
// 函数体
}
捕获列表:[] 代表空捕获列表
[name_var1, name_var2, ...] 捕获指定变量(值捕获),函数体中可以读取(值拷贝)
[&] 引用捕获,让编译器自动推导引用列表,函数体中可以进行修改(引用捕获,可以修改)
[=] 值捕获,让编译器自动推导值捕获列表,函数体中可以进行读取(值拷贝)
[this] 可以捕获类对象成员
注意:上面捕获都是捕获外部作用域声明的变量,捕获的只能时左值(有对应的内存地址),而不能捕获右值
*/
// 值捕获
void Test1()
{
int a = 1;
int b = 2;
// 返回可调用对象
auto func = [a]()
{
int c = a;
// int d = b; error 捕获列表中只值捕获a
return a; // 捕获value
};
std::cout << func() << std::endl; // 1;
// 使用仿函数直接调用, 可以捕获所以变量,值拷贝,不能修改
[=](int value)
{
int c = a; // a and b read only
int d = b;
std::cout << value << std::endl; // expect 3
}(3); // 后面加上()会立即调用(仿函数)
// 修改可读值
[a](int value) mutable
{
a = 20; // 加上可选关键字mutalbe后,可以修改只读变量,但因为是值传递,外面a变量不会被修改
return value;
}(20);
std::cout << a << std::endl; // expect 1
// 若对func可调用对象,值捕获列表值一直都是func对象生成时就绑定好了(常量)
// 不会因为捕获列表值发生变化,再次调用对象而结果不同
a++;
func();// expect 1
}
// 引用捕获
void Test2()
{
int a = 1;
int b = 2;
// 只引用捕获a变量
auto func = [&a]()
{
return ++a; // 引用捕获a并修改,外部实际值被修改
};
std::cout << a << std::endl; // expect 2;
// 引用捕获外面所有变量
[&](int value)
{
a++;
b++;
return value;
}(20);
std::cout << a << "," << b << std::endl; // expect 3,2
}
// lamdba表达式只有捕获列表为空时才能作为函数指针
void Test3()
{
using FuncType = void (*)(int, int);
FuncType func = [](int l, int r)
{
std::cout << l << "," << r << std::endl;
};
func(1, 1); // lambda无捕获参数时作为函数指针
// FuncType func1 = [=](int l, int r)
// {
// std::cout << l << "," << r << std::endl;
// };// error,捕获列表不为空时,不可以作为函数指针
// 解决1.function包装器包装可调用对象
std::function<void(int, int)> func1 = [=](int l, int r)
{
std::cout << l << "," << r << std::endl;
};
func1(2, 2);
// 解决2.使用bind绑定器返回一个仿函数对象
auto func2 = std::bind([=](int l, int r)
{ std::cout << l << "," << r << std::endl; },
3, std::placeholders::_2);
func2(10, 3); // 3, 3
}
// C++14 给与了我们方便,允许捕获的成员用任意的表达式进行初始化,这就允许了右值的捕获,
// 被声明的捕获变量类型会根据表达式进行判断,判断方式与使用 auto 本质上是相同的
void lambda_expression_capture()
{
auto important = std::make_unique<int>(1);
auto add = [v1 = 2, v2 = std::move(important)](int x, int y) -> int
{
return x + y + v1 + (*v2);
};
std::cout << add(3, 4) << std::endl; // 3 + 4 + 2 + 1
}
// 泛型lambda, c14开始之初泛型
auto fun = [](auto x, auto y){ return x+y;}
int main()
{
Test3();
return 0;
}
C++新特性lambda
于 2021-09-13 22:57:51 首次发布