概述
基本概述:
关于Lambda表达式之前接触过,但是没有系统总结过,这里整一个基础版的总结;
关于lambda表达式,可以看作三种函数调用形式的最高级别;
之前接触过:函数指针、仿函数;
lambda可以看作仿函数的升级版;
例如其他blog举例:
class Plus {
public:
int operator()(int a, int b) {
return a + b;
}
};
相比于函数指针,更容易在类内保留信息和状态,并且调用和函数类似,原因是重载了"()"操作符:
Plus plus;
std::cout << plus(11, 22) << std::endl;
// 输出 33
对于lambda而言,可以看作仿函数的升级版本;
其实对于编译器的实现而言,其本质上也是隐式构造了一个函数体,例如:
auto plus = [] (int a, int b) -> int { return a + b; }
int c = plus(1, 2);
则编译器则会将表达式翻译为:
class LambdaClass
{
public:
int operator () (int a, int b) const
{
return a + b;
}
};
LambdaClass plus;
int c = plus(1, 2);
可以看到其实就是仿函数的一种特例而已;
基本形式:
lamda表达式具体形式如下所示:
[ capture-list ] ( params ) mutable(optional) exception(optional) attribute(optional) -> ret(optional) { body };
其中exception、attribute目前先不说,后续遇到在补充;
其中ret为指定的返回形式,这里通常可以省略;
capture-list:
捕获列表主要讲述内部所需要的值是如何捕获的;
[] 什么也不捕获,无法lambda函数体使用任何
[=] 按值的方式捕获所有变量
[&] 按引用的方式捕获所有变量
[=, &a] 除了变量a之外,按值的方式捕获所有局部变量,变量a使用引用的方式来捕获。这里可以按引用捕获多个,例如 [=, &a, &b,&c]。这里注意,如果前面加了=,后面加的具体的参数必须以引用的方式来捕获,否则会报错。
[&, a] 除了变量a之外,按引用的方式捕获所有局部变量,变量a使用值的方式来捕获。这里后面的参数也可以多个,例如 [&, a, b, c]。这里注意,如果前面加了&,后面加的具体的参数必须以值的方式来捕获。
[a, &b] 以值的方式捕获a,引用的方式捕获b,也可以捕获多个。
[this] 在成员函数中,也可以直接捕获this指针,其实在成员函数中,[=]和[&]也会捕获this指针。
其中,也可以给捕获的值进行列表初始化,即进行重命名;
例如:
// 按值捕获 target,但是在 Lambda 内部的变量名叫做 v
auto cnt =
std::count_if(books.begin(), books.end(), [v = target](const Book& book) {
return book.title.find(v) != std::string::npos;
});
// 按引用捕获 target,但是在 Lambda 内部的名字叫做 r
auto cnt =
std::count_if(books.begin(), books.end(), [&r = target](const Book& book) {
return book.title.find(r) != std::string::npos;
});
也可以进行右值捕获,用于捕获“Move-only”对象,原因是"Move-only"对象无法进行引用或者复制捕获:
std::unique_ptr<int> uptr = std::make_unique<int>(123);
auto callback = [&uptr]() {
std::cout << *uptr << std::endl;
};
也可以进行指针捕获:
auto cnt =
std::count_if(books.begin(), books.end(), [p = &target](const Book& book) {
return book.title.find(*p) != std::string::npos;
});
表达式主体以及形式:
表达式主体可以直接按照函数形式进行书写,但是要注意一下啊值捕获的问题;
值捕获生成的类形式为:
auto plus = [=] (int a, int b) -> int { return x + y + a + b; };
//翻译为:
class LambdaClass
{
public:
LambdaClass(int xx, int yy)
: x(xx), y(yy) {}
int operator () (int a, int b) const
{
return x + y + a + b;
}
private:
int x;
int y;
}
int x = 1; int y = 2;
LambdaClass plus(x, y);
int c = plus(1, 2);
其中可以看到,符号运算函数为const函数,标志无法在内部进行值修改;
并且值得注意的是,捕获的值作为成员,私有持有,并且传入参数为运算符重载传入的参数;
为了避免这种情况,可以加上mutable关键字;
auto plus = [=] (int a, int b) mutable -> int { x++; return x + y + a + b; };
相应的,对于引用捕获,可以翻译为:
auto plus = [&] (int a, int b) -> int { x++; return x + y + a + b;};
//翻译形式为:
class LambdaClass
{
public:
LambdaClass(int& xx, int& yy)
: x(xx), y(yy) {}
int operator () (int a, int b)
{
x++;
return x + y + a + b;
}
private:
int &x;
int &y;
};
最后
以上就是高挑棒球为你收集整理的C/C++ Lambda表达式概述基本概述:基本形式:的全部内容,希望文章能够帮你解决C/C++ Lambda表达式概述基本概述:基本形式:所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复