Qt学习笔记(三):lambda 表达式


一、Lambda 表达式本质就是匿名函数,是 C++11 增加的新特性,所以使用 lambda 表达式的时候,需要在 Qt 项目文件(.pro) 中添加 CONFIG += C++11:

二、Lambda 表达式的语法格式为:

[capture](params) mutable ->return-type{statement}

1、[capture]:捕捉列表,作用是将外部变量传入到 lambda 表达式的内部;也是 lambda 的引出符,编译器根据该引出符判断下面的代码是 lambda 表达式;

2、(params):参数列表,作用是将参数传入到 lambda 表达式内部;如果没有参数可省略;

3、mutable :可变参数修饰符,默认情况下外部变量传入到 lambda 表达式内部后是只读的,mutable 的作用就是将 lambda 表达式内部的只读变量 变成可读可写的;mutable 也可以省略;

4、->return-type:返回类型,如果 lambda 表达式没有返回值,也可以省略;

5、{}:函数体,和普通函数一样;

三、一个最简单的 lambda 表达式:修改 mywidget.cpp 文件为:

#include "mywidget.h"
#include <QPushButton>
#include <QDebug>

MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)
{
    this->resize(400, 300);
    
    // 创建按钮对象,并通过构造函数指定父对象
    QPushButton *btn = new QPushButton(this);
    btn->setText("lamda表达式");
    btn->move(100, 80);

    /*
     * 点击按钮的时候,执行 lambda 表达式,输出一句话;
     */
    connect(btn, &QPushButton::clicked, 
            [] // lambda 表达式的引出符,编译器根据 [] 判断下面的代码是 lambda 表达式
            {
                // 函数体:和普通函数一样
                qDebug() << "我是 lamda 表达式输出的";
            }
            );
}

四、[capture]:捕捉列表

1、[] 中可以是某个(些)具体的变量名,表示 lambda 表达式内部只能获取到 [] 中指定的变量:

    int a = 10, b = 20;
    /*
     * 点击按钮的时候,执行 lambda 表达式
     */
    connect(btn, &QPushButton::clicked, 
            // 如果 [] 中是某个具体的变量名,那 lambda 表达式
            // 内部只能获取该变量,不能获取到其他变量;
            [a] 
            {
                qDebug() << "a=" << a;
                // 因为 [] 里只有一个变量 a,所以 lambda 内部只能获取
                // 到变量a,不能获取到变量 b;下面输出语句编译会报错;
//                qDebug() << "b=" << b; 
            }
            );

[] 中也可以同时存在多个变量名,以逗号分隔:

    int a = 10, b = 20, c = 30;
    /*
     * 点击按钮的时候,执行 lambda 表达式
     */
    connect(btn, &QPushButton::clicked, 
            [a, b, c] 
            {
                // lambda 表达式可以获取 [] 中的所有变量 
                qDebug() << "a=" << a;
                qDebug() << "b=" << b; 
                qDebug() << "c=" << c; 
            }
            );

2、[] 中可以是 =,表示将外部所有局部变量,以及类中所有成员以值传递方式传入到 lambda 表达式内部:

    int a = 10;
    /*
     * 点击按钮的时候,执行 lambda 表达式
     */
    connect(btn, &QPushButton::clicked, 
            [=]
            {
                // [=] 表示 lambda 表达式内部可以获取外部所有局部变量,以及类中所有的成员;
                qDebug() << "a=" << a;
                btn->setText("123");
            }
            );

3、[] 中可以是 this,表示将类中所有成员,不包括局部变量,以值传递方式传入到 lambda 表达式内部:

    int a = 10; // 局部变量
    b = 20;     // 在头文件中定义的成员变量
    /*
     * 点击按钮的时候,执行 lambda 表达式
     */
    connect(btn, &QPushButton::clicked, 
            [this]
            {
                // [this] 表示将类中所有成员,不包括局部变量,以值传递方式传入到 lambda 表达式,
                // 所以在 lambda 表达式内部只能获取到 b,不能获取到 a;
                qDebug() << "b=" << b;
//                qDebug() << "a=" << a;
            }
            );

4、[] 中可以是 &,表示将外部所有局部变量,不包括类中成员,以引用方式传递到 lambda 表达式内部:但是不建议使用 &,因为会出现内存问题,比如:

所以,总结上面捕获列表的用法可知,[] 中最常用的是 [=];

五、(params):参数列表

查看文档可知,按钮的 clicked 信号有一个参数,如下:

现在,我们把这个参数传递到 lambda 表达式内部:

    /*
     * 点击按钮的时候,执行 lambda 表达式
     */
    connect(btn, &QPushButton::clicked, 
            // 将 &QPushButton::clicked 信号的参数(bool isChecked)传入到 lambda 表达式内部
            [=](bool isChecked)
            {
                qDebug() << "isChecked=" << isChecked;
            }
            );

六、mutable :可变参数修饰符

    int a = 10; // 局部变量
    /*
     * 点击按钮的时候,执行 lambda 表达式
     */
    connect(btn, &QPushButton::clicked, 
            [=]()mutable
            {
                qDebug() << "a=" << a;
                // mutable:可变参数修饰符,如果没有 mutable 关键字,传入 lambda 内部
                // 的变量是只读的,下面赋值的语句会报错;
                // 使用 mutable 之后,变量就会变成可读可写的,才可以修改变量的值;
                a += 10;
            }
            );

七、->return-type:返回类型

前面说到 [=] 是将外部变量 以值传递的方式 传入到 lambda 表达式内部,值传递的变量在 lambda 表达式内部修改之后,外部变量的值不会变;

如果想在 lambda 表达式内部修改外部变量的值,需要在修改之后再将变量返回出去;

MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)
{
    this->resize(400, 300);
    
    // 创建按钮对象,并通过构造函数指定父对象
    QPushButton *btn = new QPushButton(this);
    btn->setText("lamda表达式");
    btn->move(100, 80);

    QPushButton *btn2 = new QPushButton(this);
    btn2->setText("lamda表达式2");
    btn2->move(100, 150);

    
    int a = 10; // 局部变量
    
    // 在外部定义一个 lambda 表达式,即匿名函数;
    // 注意:此处的 auto 理论上表示自动适配变量的类型,但是我改成
    // int 就会报错,改成其他类型也不行,只有 auto 可以编译通过;
    // [=]:表示将外部变量以值传递方式传入到 lambda 表达式内部;
    // (QString str):表示传入 lambda 表达式的参数;
    // mutable:表示将外部变量传入 lambda 内部以后变成可读可写的;
    // ->int:表示 lambda 表达式返回值的类型;
    auto func = [=](QString str)mutable->int 
                {
                    qDebug() << "a=" << a;
                    qDebug() << "str=" << str;
                    
                    // 在 lambda 表达式内部修改变量的值,然后再传出去
                    a += 10;
                    return a;
                };

    connect(btn, &QPushButton::clicked, 
            [=]()mutable
            {    
                // 调用外部定义的 lambda 表达式,并接收返回的值:
                int result = func("add");
                qDebug() << "lambda表达式返回的值:" << result;
            }
            );
    
    connect(btn2, &QPushButton::clicked, 
            [=]()
            {    
                // 以值传递的方式将变量 a 传入到 lambda 表达式内部,
                // 在表达式内部修改变量的值,外部变量的值不会变化:
                qDebug() << "在表达式内部修改变量值之后,外部变量的值:" << a;
            }
            );
}

运行结果:

  • 7
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值