一、Lambda表达式简介
Lambda表达式是C++11中的新特性,它是一种能够捕获上下文中变量,从而能够在运行时创建匿名函数的方法。Lambda表达式背后的思想是,允许我们在刻画一个函数的同一处,同时制定这个函数所操作的数据。相比于传统的函数指针,Lambda表达式具有更好地可读性和更灵活的能力。
在Qt编程中,Lambda表达式的使用非常广泛,被用于对已有的元素进行操作、遍历集合等等,Qt中的许多函数都接受Lambda表达式作为参数。
二、Qt Lambda表达式的语法
Qt Lambda表达式的形式如下:
[capture list] (parameters) mutable/specifier -> return type { statement }
其中,capture list、parameters、mutable/specifier和return type都是可选的。
下面是一个简单的示例:
auto func = [] (int a, int b) -> int { return a + b; };
此Lambda表达式为一个接受两个int参数并返回int的函数,将两个参数相加。
三、Qt Lambda表达式的用途
1.用Lambda表达式进行信号槽的连接
在Qt中,我们可以使用Lambda表达式来连接信号和槽。例如:
connect(button, &QPushButton::clicked, this, [] () { qDebug() << "Button clicked"; });
上述代码展示了如何在QPushButton的clicked信号和一个Lambda表达式之间连接槽。当按钮被点击时,连到这个槽的Lambda表达式会执行。
2.使用Lambda表达式遍历容器
另一个使用Lambda表达式的常见场景是遍历容器。我们可以通过Qt中的foreach()函数完成对容器的遍历,例如:
QVector<int> intVec {1, 2, 3}; foreach(int i, intVec) { qDebug() << i; }
上述代码展示了如何使用foreach()函数遍历一个整数向量。
我们还可以使用Qt的STL容器适配器中的C++11范围for循环语法,例如:
QVector<int> intVec {1, 2, 3}; for (const auto& i : intVec) { qDebug() << i; }
上述代码同样可以完成与前面相同的效果。
3.使用Lambda表达式进行线程控制
在Qt中,我们可以使用Lambda表达式在线程中运行任务,例如:
QThread* thread = new QThread; connect(thread, &QThread::started, [this] () { qDebug() << "Thread started"; }); connect(thread, &QThread::finished, [this] () { qDebug() << "Thread finished"; }); connect(thread, &QThread::finished, thread, &QObject::deleteLater); thread->start();
上述代码展示了如何创建一个新线程并在线程中执行Lambda表达式。
四、Qt Lambda表达式的捕获列表和可变要求
1.捕获列表
在使用Lambda表达式时,捕获列表指定Lambda表达式中应该“捕获”哪些变量。例如:
int a = 1; auto func = [a] () { qDebug() << "a is " << a; };
上述代码展示了如何捕获变量a并在Lambda表达式中使用它。
在捕获列表中,可以使用以下两种方式进行捕获:
1.值捕获
int a = 1; auto func1 = [a] () mutable { a++; qDebug() << "a is " << a; }; auto func2 = [] (int a) { qDebug() << "a is " << a; };
在上述代码中,func1和func2分别使用了值捕获。在func1中,使用了mutable关键字,允许我们修改值捕获的变量;在func2中,我们将a作为参数传递给Lambda表达式。
2.引用捕获
int a = 1; auto func = [&a] () mutable { a++; qDebug() << "a is " << a; };
在上述代码中,使用了引用捕获。Lambda表达式中捕获的是变量a的引用,因此在表达式中修改它也会反映到原变量的值上。
2.可变要求
使用mutable关键字可以将捕获的变量变成可变的,允许我们在Lambda表达式中修改它。默认情况下,变量是不可修改的。例如:
int a = 1; auto func = [a] () mutable { a++; qDebug() << "a is " << a; };
在上述代码中,使用了mutable关键字,允许我们在Lambda表达式中修改变量a的值。
五、总结
Qt Lambda表达式的使用方式非常灵活,不仅可以用于信号槽的连接、容器的遍历,还可以在多线程编程中使用。捕获列表和可变要求为Lambda表达式带来了更高的可定制性,并且代码的可读性更强。
六、完整代码示例
下面是一个使用Qt Lambda表达式的完整示例:
#include <QtGlobal> #include <QDebug> #include <QVector> #include <QThread> void connectButton(); void traverseVector(); void runInThread(); int main(int argc, char *argv[]) { Q_UNUSED(argc); Q_UNUSED(argv); connectButton(); traverseVector(); runInThread(); return 0; } void connectButton() { QPushButton* button = new QPushButton("Click me!"); connect(button, &QPushButton::clicked, [] () { qDebug() << "Button clicked"; }); button->show(); } void traverseVector() { QVector<int> intVec {1, 2, 3}; foreach(int i, intVec) { qDebug() << i; } for (const auto& i : intVec) { qDebug() << i; } } void runInThread() { QThread* thread = new QThread; connect(thread, &QThread::started, [thread] () { qDebug() << "Thread started"; }); connect(thread, &QThread::finished, [thread] () { qDebug() << "Thread finished"; }); connect(thread, &QThread::finished, thread, &QObject::deleteLater); thread->start(); }