定义
C++11中的Lambda表达式用于定义并创建匿名的函数对象,以简化编程工作。
Lambda表达式的基本构成:
[capture](parameters) mutable ->return-type
{
statement
}
[函数对象参数](操作符重载函数参数)mutable ->返回值{函数体}
函数对象参数;
[],标识一个Lambda的开始,这部分必须存在,不能省略。函数对象参数是传递给编译器自动生成的函数对象类的构造函数的。函数对象参数只能使用那些到定义Lambda为止时Lambda所在作用范围内可见的局部变量(包括Lambda所在类的this)。函数对象参数有以下形式:
- 空。没有使用任何函数对象参数。
- =。函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda所在类的this),并且是值传递方式(相当于编译器自动为我们按值传递了所有局部变量)。
- &。函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda所在类的this),并且是引用传递方式(相当于编译器自动为我们按引用传递了所有局部变量)。
- this。函数体内可以使用Lambda所在类中的成员变量。
- a。将a按值进行传递。按值进行传递时,函数体内不能修改传递进来的a的拷贝,因为默认情况下函数是const的。要修改传递进来的a的拷贝,可以添加mutable修饰符。
- &a。将a按引用进行传递。
- a, &b。将a按值进行传递,b按引用进行传递。
- =,&a, &b。除a和b按引用进行传递外,其他参数都按值进行传递。
&, a, b。除a和b按值进行传递外,其他参数都按引用进行传递。
引用的例子
这里相关&的例子
#include <iostream>
using namespace std;
int main()
{
int a = 10;
//1
auto lambda_val = [a]()->int{return a+1;};
auto lambda_ref = [&a]()->int{return a+1;};
//2
cout << "val " << lambda_val() << endl;
cout << "ref " << lambda_ref() << endl;
//3
a++;
cout << "val " << lambda_val() << endl;
cout << "ref " << lambda_ref() << endl;
return 0;
}
打印结果
val 101
ref 101
val 101
ref 102
分析:
在(1)处,lambda_val()中捕获到a,在lambda_val()函数内部,a已经被拷贝赋值;lambda_ref()中捕获到a的引用,实际操作的还是父域中的a;
在(3)处,lambda_val()中a还是(1)拷贝来的10,输出a+1=11;lambda_ref()中(1)捕获的a的引用,由于受到父域a++,a=11的影响,返回a+1=12。
简写与直接使用
实际上我们可以忽略参数列表和返回类型,但必须永远包含捕获列表和函数体,忽略参数列表等价于指定一个空函数列表,忽略返回类型,lambda会根据函数体中的代码推断出来(如果函数体直接return,则是void类型)
上面代码直接写成
auto lambda_val = [a](){return a+1;};
auto lambda_ref = [&a](){return a+1;};
当然可以直接使用lambda函数,如下:
int a = 100;
cout<<[](int input){return input*input;}(a)<<endl;
int b = 100;
cout<<[b](){return b*b;}()<<endl;
mutable
若用lambda想改变外部参数,可以使用mutable修饰符,例子如下
int a = 100;
cout<<a<<endl;
[&a]()mutable{
a++;
}();
cout<<a<<endl;//101
c++14
C++14 标准介绍了通用化的 lambda 表达式,允许我们用 auto 来作为一个 lambda 表达式的参数类型。我们可以写一段更简洁、更优雅的代码
auto func = [](auto input) { return input * input; };
QT槽函数使用
在Qt里,还可以直接当作槽函数
QPushButton * myBtn = new QPushButton("First Button",this);
myBtn->move(100,100);
connect(myBtn,&QPushButton::clicked,this, [](){qDebug()<<"I am a slot";});