C/C++_Lambda表达式

Posted 17岁boy想当攻城狮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C/C++_Lambda表达式相关的知识,希望对你有一定的参考价值。

Lambda是C++11特性,用于创建匿名函数,匿名函数即只拥有函数体,但是没有函数名。

你可以把他理解为一小段代码,但是又不需要像函数哪有,执行函数现场保护。

推出这种表达式主要目的是为了解决一次性函数,如当我们在编写一段代码想要处理某些事情得时候,我们需要编写一段代码,其中有一段代码下面是要可以复用的,但是它只限于当前函数使用,一次性的函数,如果为其单独编写一个函数未免有些浪费资源,和编写一些无用代码,但是不写的话,下面又要重写一段与上面一样的代码。

这个时候,Lambda就诞生了,在这种情况下我们可以使用Lambda表达式来完成复用代码,编写一次性的函数。

先看一下Lambda表达式原型:

[捕获方式] (参数)  {函数体}

首先介绍一下捕获方式:

[]:
没有任何捕获方式,仅仅是一段代码

[=]
函数体内可以使用 Lambda 所在范围内所有可见的局部变量(包括 Lambda 所在类的 this但不包括成员变量),并且是值传递方式(相当于编译器自动为我们按值传递了所有局部变量),传值传递的变量相当于左值引用,不可修改,如果要修改要加上mutable告诉编译器这个值是永远可变的。
同时mutable只能用于类的成员变量

[&]
函数体内可以使用 Lambda 所在范围内所有可见的局部变量(包括 Lambda 所在类的 this),并且是引用传递方式(相当于是编译器自动为我们按引用传递了所有局部变量)。

[this]
函数体内可以使用 Lambda 所在类中的成员变量。

[变量x]
将变量x按值进行传递。按值进行传递时,函数体内不能修改传递进来的 a 的拷贝,因为默认情况下函数是 const 的,要修改传递进来的拷贝,可以添加 mutable 修饰符。

[&变量x]
将变量x按引用进行传递。

[变量x,&变量x1]
将变量x按值传递,变量x1按引用进行传递。

[=,&变量x,&变量x1]
除变量x和变量x1按引用进行传递外,其他参数都按值进行传递。

[&,变量x,变量x1]
除变量x和变量x1按值进行传递外,其他参数都按引用进行传递。

参数:

参数,像普通函数那样定义你的参数就可以了。

函数体:

在函数体里可以随意编写代码。

值得一提的是,lambda不能访问超过所在区域的变量,如lambda在函数体里,那么它不能访问全局变量,换句话说,如果它在全局里,它可以访问全局变量,但不能访问别的函数体里的局部变量,其次是它不能引用静态变量,因为静态变量不属于局部变量。

其次是,lambda使用=传递时,会创建变量的副本(需要额外的栈空间),但是是const类型的,如果你修改它的值但是不会危险到原本变量里的值。

这是一段列子:

int main()
{
    int j = 0;
    auto df = [=]{return j;}();
    printf("%d\\n",df);
    return 0;
}

输出结果为0,如果你的Lambda表达式里无需参数,那么在使用时,不要加上(),否则会报错。

同时如果没有参数的话,表达式里的参数()可以放到末尾

如果有参数的情况下不行:

int main()
{
    int j = 0;
    auto df = [=](int a){return j+a;};
    printf("%d\\n",df(10));
    return 0;
}

输出为“10”

使用引用的情况下是可以修改值的:

int main()
{
    int j = 0;
    auto df = [&](int a){
    j = j+10;
    return j+a;};
    printf("%d\\n",df(10));
    return 0;
}

输出20

但是引用传递的是副本,切记是副本!!不会改变其本身值:

int main()
{
    int j = 0;
    auto df = [&](int a){
    j = j+10;
    return j+a;};
    printf("%d\\n",df(10));
    printf("%d\\n",j);
    return 0;
}

输出:

20

10

当然你也可以使用函数指针来指向它,依然是合法的:

auto a_lambda_func = [](int x) { /* ... */ };
void (*func_ptr)(int) = a_lambda_func;
func_ptr(4); // calls the lambda

补充:

在类的内部使用"&"或者“=”方式捕获是可以捕获成员变量的

其次lambda表达式是可以用在QT的参数上的。

注意这种写法仅限于QT5,在QT5时,QT的开发者们新增了connect的重载函数,且让编译器支持了使用lambda用于参数。

如:

myTimer = new QTimer(this);
connect(myTimer, &QTimer::timeout, [=](){
        static int i = 0;
        i++;
        ui->lcdShow->display(i);
});

当然更直观可以这样写:

myTimer = new QTimer(this);
auto lam = [=](){
        static int i = 0;
        i++;
        ui->lcdShow->display(i);
};
connect(myTimer, &QTimer::timeout, lam);

connect也支持函数指针的写法

以上是关于C/C++_Lambda表达式的主要内容,如果未能解决你的问题,请参考以下文章

C++Lambda表达式作为参数

C++Lambda表达式作为参数

C++Lambda表达式作为参数

C++C++中的lambda表达式和函数对象

[C/C++11语法]_[初级]_[lamba 表达式介绍]

IntelliJ:求值lambda表达式在调试时引发编译错误