Qt - Lambda表达式

17 篇文章 1 订阅

Lambda 表达式

Lambda 表达式是一个匿名函数。

这里从使用 std::sort 的写法看C++标准的发展:

ISO C++ 98 标准下,需要这样写:

bool compare(int& a,int& b)
{
    return a>b;
}

sort(a, a+n, compare);

而到了 ISO C++ 11 标准中引入 Lambda,代码将简洁很多:

sort(a, a+n, [](int a,int b){return a>b;});

ISO C++14 支持基于类型推断的泛型 Lambda 表达式,上面的代码可以改写为:

sort(a, a+n, [](const auto& a,const auto& b){return a>b;});

由于 Lambda 的类型是单一的,不能通过类型名来显式声明对应的对象,一般我们利用 auto 关键字和类型推导:

auto f = sort(a, a+n, [](const auto& a,const auto& b){return a>b;});

语法格式

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

[capture]

捕获列表,作用是将外部变量传入到 Lambda 表达式的内部,不可省略

捕获表达式变量

C++14 中引入了表达式捕捉,其允许用任何类型的表达式初始化捕捉的变量。

// 利用表达式捕获,可以更灵活地处理作用域内的变量
int x = 4;
auto y = [&r = x, x = x + 1] { r += 2; return x * x; }();
auto z = [str = "string"] { return str; }();

有时候你可以用 std::move 初始化变量。这对不能复制只能移动的对象很重要,比如 std::unique_ptr,因为其不支持复制操作,你无法以值方式捕捉到它。但是利用 Lambda捕捉表达式,可以通过移动来捕捉它:

auto myPi = std::make_unique<double>(3.1415);
auto circle_area = [pi = std::move(myPi)](double r) { return *pi * r * r; };
cout << circle_area(1.0) << endl; 

捕获作用域变量

  • null,没有使用任何函数对象参数。

  • =,可使用Lambda所在作用域范围内的所有可见的局部变量,并才有值传递的方式传入。

  • &,可使用Lambda所在作用域范围内的所有可见的局部变量,并才有引用传递的方式传入。

  • this,可使用Lambda所在类内的成员变量。

  • variate,默认情况是const的,如果需要修改应加上mutable ;将variate以值传递形式传入。

  • &variate,将variate以引用传递的形式传入。

  • 组合,可用 ,隔开,例: [&, variate]

  • 包扩展

    template<class... Args>
    	void f(Args... args) {
        	auto x = [args...] { return g(args...); };
       	 x();
    }
    

注意点

  • 引用捕获可用于修改外部变量,但值捕获不能。
  • 引用捕获会反映外部变量的更新,而值捕获则不会。
  • 引用捕获引入生存期依赖项,而值捕获却没有生存期依赖项。

(params)

参数列表,作用是将参数传入到 lambda 表达式内部,如果没有参数可省略。

auto y = [] (int first, int second)
{
    return first + second;
};

在C++14中,我们好可以使用auto,实现泛型:

auto y = [] (auto first, auto second)
{
    return first + second;
};

mutable

可变参数修饰符,默认情况下外部变量传入到 lambda 表达式内部后是 只读 的,mutable 的作用就是将 Lambda 表达式内部的只读变量变成 可读可写 的。

如果是值传入的方式,对传入变量的修改仅在Lambda内有效(值传递创建副本)。

mutable 也可以省略。

constexpr

C++11 提供了constexpr 让用户显式的声明函数或对象构造函数在编译器会成为 常数

这个关键字明确的告诉编译器在编译时就去验证是否为常数。是一种比 const 更强的约束,这样可以得到更好的效率和安全性。

constexpr 也可省略。

noexcept

指定 Lambda 表达式可以抛出的异常,它可省略。

该关键字告诉编译器,函数中不会发生异常,这有利于编译器对程序做更多的优化。

如果 noexecpt函数 向外抛出了异常,程序会直接终止,调用 std::terminate() 函数,该函数内部会调用 std::abort() 终止程序。

注意:如果函数内部捕捉了异常并完成处理,这种情况不会继续向下抛出异常,即对noexecpt无法捕获该异常。

->return type

返回值, 如果 lambda 主体只包含一个返回语句,则可以省略 lambda 表达式的返回类型部分,编译器将自动推导。

auto x1 = [](int i){ return i; }; 

{}

函数执行体,和普通函数一样。

Qt connect

QPushButtonclicked 为例:

在这里插入图片描述

connect(btn, &QPushButton::clicked, [=](bool isChecked){
           qDebug() << "isChecked=" << isChecked;
       });

参考鸣谢

C++ 中的 Lambda 表达式

C++ 中的lambda表达式

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值