• Qt中使用匿名函数lambda表达式


    一、为什么要使用匿名函数lamdba

    首先,lambda表达式可以使代码变得简单,C++中,一个lambda表达式表示一个可调用的代码单元。如代码:

    #include <QCoreApplication>
    #include <QDebug>
    #include <QSharedPointer>
    
    int func2(int i)
    {
       i += 2;
       return i+4;
    }
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
    
        auto func1 = [](int i) {i += 2; return i+4; };
        qDebug()<< "func2: " << func2(6) << '
    ';
        qDebug()<< "func1: " << func1(6) << '
    ';
    
        return a.exec();
    }
    

      如上,对于一个简单的计算,我们可以通过定义函数的形式,或者使用匿名函数的方法来实现。当然,如果这个函数功能十分简单,不会被重复使用,又不至于单独写一个函数,可以通过匿名函数简化代码:

    int result  = 0;
    bool isAdd = false;
    result = isAdd? [](int a,int b){return a+b;}(10,5):[](int a,int b){return a-b;}(10,5);
    qDebug()<<result<<endl;
    

      如上可以简单的示例简化的作用。

    二、匿名函数中于外部的交互

    int n = 2;
    qDebug()<<[n](int n1){return n1+n;}(3)<<endl;
    

      如上,方括号[]用来传递局部变量,可在[]内枚举函数体内需要用到的局部变量。使用[=]则外部的所有变量函数体内都可使用。同理[&]用引用的方法也相同,但是如果需要引用的变量是动态的,例如指针,则这种方法可能会引发出错,内存释放不及时,导致其他变量的值出错。[this]这也类似,都能使用函数体外部的变量。

      如果想要修改操作外面的变量:

    int n = 2;
    qDebug()<<[&](int n1){n = 3;return n1+n;}(3)<<endl;  //6
    qDebug()<<n<<endl;  //3
    

      注意,[] 里面获取n和通过=获取所有的变量都只是只读的,不能修改!!!如果只是想要内部修改,不改变局部变量实际值的话,可以通过关键字 mutable实现:

    int n = 2;
    qDebug()<<[=](int n1)mutable {n = 3;return n1+n;}(3)<<endl;  //6
    qDebug()<<n<<endl;  //2
    

      

    三、匿名函数在connect中的使用

      事实上,匿名函数作为一个槽函数是非常方便的。

    Widget::Widget(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Widget)
    {
        ui->setupUi(this);
    
        int n = 0;
        QTimer *timer = new QTimer(this);
        connect(timer, &QTimer::timeout,this, [=]()mutable {n += 1;qDebug()<<n<<endl;});
        timer->start(1000);
    
    }
    

      注意,lamda匿名函数对应的信号必须是函数指针的形式。

      注意:通过mutable的使用,如果是类中的变量的话,是可以修改的,如果是局部变量是修改不了的,代码示例:

    Widget::Widget(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Widget)
    {
        ui->setupUi(this);
        n = 0;
        QTimer *timer = new QTimer(this);
        connect(timer, &QTimer::timeout,this, [=]()mutable {n += 1; if(n == 3){timer->stop();}qDebug()<<n<<endl;});
        timer->start(1000);
    }
    void Widget::on_pushButton_clicked()
    {
        qDebug()<<n<<endl;
    }
    

      如上,我对于定时器跳到n为3的时候就停下来,然后按按钮,查看当前的n的值,发现类中属性n为3。

    Widget::Widget(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Widget)
    {
        ui->setupUi(this);
    
        n = 0;
        qDebug()<<[=](int n1)mutable {n += 3;return n1+n;}(3)<<endl;  //6
        qDebug()<<n<<endl;  //3
    
    }
    

      如果n为局部变量的话:

    Widget::Widget(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Widget)
    {
        ui->setupUi(this);
    
        int n = 0;
        qDebug()<<[=](int n1)mutable {n += 3;return n1+n;}(3)<<endl;  //6
        qDebug()<<n<<endl;  //0
    
    }
    

      

  • 相关阅读:
    程序的本质复杂性和元语言抽象
    编译器词法消歧设计
    关于分工的思考 (Thoughts on Division of Labor)
    数据即代码
    类型的本质和函数式实现
    二叉树迭代器算法
    kvm虚拟化存储管理
    kvm网络虚拟化管理
    kvm虚拟机的四种网络模式
    Linux 中交换空间 (swap)应该分多大才好?
  • 原文地址:https://www.cnblogs.com/pinking/p/10991850.html
Copyright © 2020-2023  润新知