C++11特性之lambda表达式

目录

1.定义

2.捕获列表

3.返回值

        自动推导返回类型

        显示指定推导类型

4.mutable关键字

5.应用

       1. 作为算法的参数

        2.作为回调函数


1.定义

        Lambda 表达式(也称为匿名函数)是 C++11 引入的一种便捷的函数定义方式。它允许在需要函数对象的地方快速定义一个匿名函数,而不需要像传统函数那样先定义函数体,再通过函数名调用。

语法:[capture](params)->ret{body};

        其中capture是捕获列表,params是参数列表,ret是返回值类型,body是函数体。

捕获列表[]:捕获一定范围内的变量

参数列表():和普通函数的参数列表一样,如果没有参数参数列表可以省略不写

它具有以下优点:

        1.可以就地的匿名定义目标函数或函数对象,不需要额外的写一个函数

        2.lambda表达式是一个匿名的内联函数

2.捕获列表

        [] : 不捕获任何变量

        [&] :捕获外部作用域中的所有变量,并按照引用捕获

        [=]捕获外部作用域中的所有变量,按值捕获,拷贝过来的副本在函数体内是只读的

        [=,&a] 按值捕获外部作用域的所有变量,并且按照引用捕获外部变量a

        [bar] 按值捕获bar变量法,不捕获其他变量

        [this] 捕获当前类中的this指针,让lambda表达式拥有和当前类成员函数同样的访问权限

int main(){
    int a=10,b=20;
    auto f1=[]{return a;};//错误,没有捕获外部变量,因此无法访问变量a
    auto f2=[&]{return a++;};//正确,使用引用的方式捕获外部变量,可读写
    auto f3=[=]{return a;};//正确,使用值拷贝的方式捕获外部变量,可读
    auto f4=[=]{return a++;};//错误,使用值拷贝的方式捕获外部变量,可读不可写
    auto f5=[a]{return a+b;};//错误,使用拷贝的方式捕获了外部变量a,没有捕获外部变量b,因此无法访问变量b
    auto f6=[a,&b]{return a+(b++);};//正确,使用拷贝的方式捕获了外部变量a,只读,没有使用引用的方式捕获外部变量b,可读写
    auto f7=[=,&b]{return a+(b++);};//正确,使用值拷贝的方式捕获所有外部变量以及b的引用,b可读写,其他只读
    
}



class Test{
public:
    int num;
    void output(int x ,int y)
    {
        auto x1=[]{return num;};//错误,没有捕获外部变量,不能使用类成员
        auto x2=[=]{return num+x+y;};//正确,以值拷贝不糊所有外部变量
        auto x3=[&]{return num+x+y;};//正确,以引用的方式捕获外部所有变量
        auto x4=[this]{return num;};//正确 ,捕获this指针,可访问对象内部成员
        auto x5=[this]{return num+x+y;};//错误,捕获this指针,可访问类内部成员,没有捕获到x和y ,因此不能访问
        auto x6=[this,x,y]{return num+x+y;};//正确
        auto x7=[this]{return num++;};//正确,捕获this指针,并且可以修改对象内部变量的值           
    }   
};

可以根据上述例子熟悉一下lambda表达,这里就不在过多说明。

3.返回值

        自动推导返回类型

        一般情况下,不指定lambda表达式的返回值,编译器会根据return语句自动推导出返回值类型,但是需要注意的是lambda表达式不能通过列表初始化自动对到返回值类型。

//可以自动推导出返回值类型
auto f=[](int i){
    return i;
}
//不能推导出返回值类型
auto f1=[](){
    return {1,2};
}

        显示指定推导类型

        当自动推导可能出现问题或者需要明确返回类型时,可以使用->来显式指定返回类型。例如[](double a, double b) -> double { return a / b; },这里明确指定了返回类型为double

4.mutable关键字

        默认情况下,lambda 表达式的operator()函数是const的,即不能修改通过值捕获的变量。如果想要修改通过值捕获的变量,就需要使用mutable关键字。

例如:

     int num = 10;
     auto lambda3 = [num]() mutable { num = 20; return num; };

这里lambda3通过值捕获了num,由于使用了mutable,在 lambda 表达式内部可以修改num的值。

5.应用

       1. 作为算法的参数

        在进行排序的时候,我们往往需要重写一个比较器的函数,例如:

#include<iostream>
#include <vector>
#include<algorithm>
using namespace std;
bool cmp(int a, int b) {
	return a < b;
}
int main() {
	vector<int> v = { 1,8,9,7,5,2 };
	sort(v.begin(), v.end(), cmp);
	for (auto i : v) {
		cout << i << " ";
	}
	return 0;
}

假如这里我们用lambda表达式,就可以写成这样:

#include<iostream>
#include <vector>
#include<algorithm>
using namespace std;
int main() {
	vector<int> v = { 1,8,9,7,5,2 };
	sort(v.begin(), v.end(), [](int a, int b) { return a < b; });
	for (auto i : v) {
		cout << i << " ";
	}
	return 0;
}

        2.作为回调函数

        在图形用户界面(GUI)编程或者事件驱动编程中,lambda 表达式可以作为回调函数来处理事件。比如在一个简单的按钮点击事件处理中,可以使用 lambda 表达式来定义按钮被点击时要执行的操作。

        例如在Qt中,有一个pushButton按钮,点击它的槽函数就可以用到lambda表达式

QObject::connect(&button, &QPushButton::clicked, [&]() {
        // 这里定义按钮点击时要执行的操作,比如简单地弹出一个消息框提示按钮被点击了
        QMessageBox::information(&window, "Button Clicked", "You clicked the button!");
    });

connect函数有四个参数,如果用lambda表达式就可以替换后面的两个参数。这样可以简化,避免去再写一个函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值