【学习笔记】QT从入门到实战完整版(Lambda)(2)
Lambda
Lambda 表达式很有意思,相信很多人初次见到 Lambda 表达式都会不能理解有什么用,我也一样,看了视频教程之后,突然意识到,Lambda 真的是太好用了,它可以在某些情况下可以很大程度上简化代码。
应用场景
下面的代码给我的启发:实现通过信号槽的方式实现点击按钮时,触发修改按钮的名字为“停止”。connect 的最后一个参数其实是函数指针,当按钮触发了 clicked 信号时,将会调用该函数指针,那么借助 Lambda 就不需要重新另外定义一个成员函数来作为参数传入。
void Widget::testLambda()
{
QPushButton *pButton = new QPushButton();
pButton->setParent(this);
pButton->setText("启动");
connect(pButton, &QPushButton::clicked, this, [=](){
pButton->setText("停止");
});
}
可以自己写一个函数回调的方式来对比
#include <iostream>
void onEvent()
{
printf("onEvent\n");
}
void notice(void (*pfunc)())
{
pfunc();
}
int main(int argc, char *argv[])
{
notice(onEvent);
return 0;
}
使用 Lambda 的方式,可以看到代码简化了
#include <iostream>
void notice(void (*pfunc)())
{
pfunc();
}
int main(int argc, char *argv[])
{
notice( [](){printf("Lambda2\n");} );
return 0;
}
介绍说明
从上面的例子可以看到,Lambda 其实本质就是一个函数,只不过这个函数没有名字,所以也叫匿名函数。适合在一些需要传递以函数为参数的表达式中,而函数本事的实现只有几句代码,可以不必另外声明定义函数,直接使用 Lambda 即可。
Lambda 原型说明:
[外部变量访问方式说明符] (参数表) 修饰符 ->返回值类型 {函数体} ()
Lambda 原型解析:
[外部变量访问方式说明符] :
用于确定 Lambda 函数体可以用何种方式去访问外部成员
- [] 中括号里面为空,即表示不访问任何外部成员变量。
- [&] 以引用方式使用 Lambda 所在作用范围内所有可见的局部变量(包括Lambda所在类的 this)。
- [=] 以值传递方式使用 Lambda 所在作用范围内所有可见的局部变量(包括Lambda所在类的 this)。
- [=, &a] 除了a以引用传递方式使用,其他的所有变量以值传递方式使用。
- [a] 只取a,并且以值传递方式使用。
- [this] 取 Lambda 所在的类中的 this 指针。如果已经使用了 & 或者 = 就默认添加此选项。
代码示例:
void Widget::showString(char *pString)
{
qDebug() << pString;
}
void Widget::testLambda()
{
int a = 1;
int b = 2;
// [] 方式
qDebug() << "[] 方式";
[]()
{
// int x = a + b; // 会报错, 因为 a、b 不可见
qDebug() << "调用中:";
}();
// [&] 方式
qDebug() << "\n[&] 方式";
qDebug() << "调用前: " << "a:" << a << " b:" << b;
[&]()
{
a = 5;
b = 3;
qDebug() << "调用中: "<< "a:" << a << " b:" << b;
this->showString("[&] 方式使用成员函数 showString()");
}();
qDebug() << "调用后: " << "a:" << a << " b:" << b;
// [=] 方式
qDebug() << "\n[=] 方式";
qDebug() << "调用前: " << "a:" << a << " b:" << b;
[=]()
{
// a = 5; // 会报错, 变量默认为只读属性, 需要使用 mutable 修饰符才可以修改
qDebug() << "调用中: "<< "a:" << a << " b:" << b;
this->showString("[] 方式使用成员函数 showString()");
}();
qDebug() << "调用后: " << "a:" << a << " b:" << b;
// [=, &a] 方式
qDebug() << "\n[=, &a] 方式";
qDebug() << "调用前: " << "a:" << a << " b:" << b;
[=, &a]()
{
a = 16;
// b = 7; // 会报错, b变量默认为只读属性, 需要使用 mutable 修饰符才可以修改
qDebug() << "调用中: "<< "a:" << a << " b:" << b;
this->showString("[=, &a] 方式使用成员函数 showString()");
}();
qDebug() << "调用后: " << "a:" << a << " b:" << b;
// [a] 方式
qDebug() << "\n[a] 方式";
qDebug() << "调用前: " << "a:" << a << " b:" << b;
[a]()
{
//a = 16; // 会报错, a变量默认为只读属性, 需要使用 mutable 修饰符才可以修改
//qDebug() << "调用中: "<< "a:" << a << " b:" << b; // 会报错, b 变量不可见
// this->showString("[a] 方式使用成员函数 showString()"); // 会报错, this 不可见
qDebug() << "调用中: "<< "a:" << a;
}();
qDebug() << "调用后: " << "a:" << a << " b:" << b;
// [this] 方式
qDebug() << "\n[this] 方式";
qDebug() << "调用前: " << "a:" << a << " b:" << b;
[this]()
{
// qDebug() << "调用中: "<< "a:" << a << " b:" << b; //会报错 a、b 都不可见
this->showString("[this] 方式使用成员函数 showString()");
}();
qDebug() << "调用后: " << "a:" << a << " b:" << b;
}
运行结果
[] 方式
调用中:
[&] 方式
调用前: a: 1 b: 2
调用中: a: 5 b: 3
[&] 方式使用成员函数 showString()
调用后: a: 5 b: 3
[=] 方式
调用前: a: 5 b: 3
调用中: a: 5 b: 3
[] 方式使用成员函数 showString()
调用后: a: 5 b: 3
[=, &a] 方式
调用前: a: 5 b: 3
调用中: a: 16 b: 3
[=, &a] 方式使用成员函数 showString()
调用后: a: 16 b: 3
[a] 方式
调用前: a: 16 b: 3
调用中: a: 16
调用后: a: 16 b: 3
[this] 方式
调用前: a: 16 b: 3
[this] 方式使用成员函数 showString()
调用后: a: 16 b: 3
(参数表) :
用于确定 Lambda 传入那些变量作为参数提供给 Lambda 函数体使用,如果没有可以省略 “()” 括号。
#include <iostream>
void onEvent(int type)
{
printf("onEvent:%d\n", type);
}
void notice(void (*pfunc)(int type), int type)
{
pfunc(type);
}
int main(int argc, char *argv[])
{
// 传统的方式, 回传参数
notice(onEvent, 5);
// lambda 方式 一 , 回传参数
notice([](int type) {printf("Lambda :%d\n", type); }, 15);
// lambda 方式 二 , 回传参数
auto func = [](int c, int d)
{
printf("AutoFunc: c: %d d:%d\n",c ,d);
};
// 调用
func(8, 9);
return 0;
}
修饰符:
如果没有修饰符则可以省略不写
mutable:
用于修饰 [外部变量访问方式说明符] 中列举的按值传递方式的变量时,可以修改其拷贝值。
相当于 void func(const int a, const int b) 变为 void func(int a, int b)
当有此修饰符时,引入的外部变量不能为空。
void Widget::testLambda()
{
int a = 1;
int b = 2;
// mutable
qDebug() << "\nmutable";
qDebug() << "调用前: " << "a:" << a << " b:" << b;
[a, b] () mutable
{
a = 16; // 由于是值传递,a 其实是 lambda 函数体内的局部变量,所以修改的只是 a 的拷贝
b = 100;
qDebug() << "调用中: "<< "a:" << a << " b:" << b; // 会报错, b 变量不可见
}();
qDebug() << "调用后: " << "a:" << a << " b:" << b;
}
mutable
调用前: a: 1 b: 2
调用中: a: 16 b: 100
调用后: a: 1 b: 2
exception:
说明 lambda 表达式是否抛出异常(noexcept),以及抛出何种异常,类似于void f()throw(X, Y)
->返回值类型 :
说明 lambda 函数体可以返回什么样类型的值,实际测试中似乎无论什么情况都可以省略,编译器会自动推测出类型。
#include <iostream>
void notice(int (*pfunc)(int a, int b), int aa, int bb)
{
printf("notice:%d\n",pfunc(aa, bb));
}
int main(int argc, char *argv[])
{
// lambda, 回传参数
notice(
[](int a, int b)
{
printf("回调隐式返回类型: a:%d b:%d a+b:%d\n", a, b, a + b);
return a + b;
},
10, 15);
puts("");
// lambda, 回传参数
notice(
[](int a, int b)->int
{
printf("回调显式返回类型: a:%d b:%d a+b:%d\n", a, b, a + b);
return a + b;
},
10, 15);
puts("");
// lambda, 显式返回类型
auto func = [](int c, int d)->int
{
printf("显式返回类型: c:%d d:%d c+d:%d\n",c ,d, c + d);
return c + d;
};
// 调用
printf("func:%d\n", func(20, 10));
puts("");
// lambda, 隐式返回类型(视频中说只有一处才可以省略,但实际做的实验发现都可以)
auto func1 = [](int c, int d)
{
printf("隐式返回类型: c:%d d:%d c+d:%d\n", c, d, c + d);
if (c > 3)
return c + d;
else
return c;
};
// 调用
printf("func1:%d\n", func1(50, 10));
return 0;
}
{函数体} :
实际具体的实现,一般都只有几句代码。
():
最后这一个括号其实代表的是调用的意思,当需要执行时,加上括号即可。
// 只是定义, 并未调用
[]()
{
printf("11111111111111\n");
};
// 定义了且被调用了
[]()
{
printf("11111111111111\n");
}();
// 最简单的 lambda 表达式
[] {puts("lambda..."); };
【学习笔记】QT从入门到实战完整版(Lambda)(2)的更多相关文章
- 2579页阿里P8Android学习笔记在互联网上火了,完整版开放下载
笔记作者:来自于阿里P8级大神: Mark 笔记特点:条理清晰,理论+实战+源码,含图像化表示更加易懂. 内容概要:Android 相关,性能优化,Java 相关,Kotlin 相关,网络相关,插件化 ...
- Hadoop学习笔记(1) ——菜鸟入门
Hadoop学习笔记(1) ——菜鸟入门 Hadoop是什么?先问一下百度吧: [百度百科]一个分布式系统基础架构,由Apache基金会所开发.用户可以在不了解分布式底层细节的情况下,开发分布式程序. ...
- iOS学习笔记-地图MapKit入门
代码地址如下:http://www.demodashi.com/demo/11682.html 这篇文章还是翻译自raywenderlich,用Objective-C改写了代码.没有逐字翻译,如有错漏 ...
- tensorflow学习笔记二:入门基础 好教程 可用
http://www.cnblogs.com/denny402/p/5852083.html tensorflow学习笔记二:入门基础 TensorFlow用张量这种数据结构来表示所有的数据.用一 ...
- 电子书下载:Delphi XE 5 移动开发入门手册(完整版)
更多电子书请到: http://maxwoods.400gb.com 下载:Delphi XE5移动开发入门手册(完整版)
- spark学习笔记总结-spark入门资料精化
Spark学习笔记 Spark简介 spark 可以很容易和yarn结合,直接调用HDFS.Hbase上面的数据,和hadoop结合.配置很容易. spark发展迅猛,框架比hadoop更加灵活实用. ...
- Android学习笔记(二十一)——实战:程序数据共享
//此系列博文是<第一行Android代码>的学习笔记,如有错漏,欢迎指正! 我们继续在Database项目的基础上继续开发,通过内容提供器来给它加入外部访问接口.首先将 MyDataba ...
- Android学习笔记(十五)——实战:强制下线
//此系列博文是<第一行Android代码>的学习笔记,如有错漏,欢迎指正! 实现强制下线功能的思路也比较简单,只需要在界面上弹出一个对话框, 让用户无法进行任何其他操作, 必须要点击对话 ...
- Android学习笔记(十二)——实战:制作一个聊天界面
//此系列博文是<第一行Android代码>的学习笔记,如有错漏,欢迎指正! 运用简单的布局知识,我们可以来尝试制作一个聊天界面. 一.制作 Nine-Patch 图片 : Nine-Pa ...
- SQL学习笔记——SQL初入门,Ubuntu下MySQL的安装
刚开始接触sql,于是准备在Ubuntu下学习sql,就跟着itercast的sql教程开始入门了. 下面只是我个人的记录,高手请绕道: 一. 在安装之前,我们可以用下面这个命令通过开放端 ...
随机推荐
- DTSE Tech Talk | 第9期:EiPaaS驱动企业数字化转型
摘要: 揭秘华为企业集成新模式. 本期直播详解 组装式概念解析 EiPaaS的核心技术能力 华为实践经验分享 EiPaaS未来的技术趋势 直播讲师:华为云PaaS DTSE布道师 傅翌伟 tips:E ...
- 微信支付v3接口的 官方 Java SDK
啰嗦几句:微信支付v3版接口麻烦吗?在对接微信支付v3接口时,本来是一件很简单的事情,其实微信支付v3接口并不是很复杂,但是微信团队的管理很混乱,给我们开发者带来了巨大的麻烦. 微信支付v3版接口对接 ...
- Python基础之函数:5、内置函数、迭代器对象、异常的捕获和处理
目录 一.重要内置函数 1.zip() 2.filter() 3.sorted() 二.常见内置函数 1. abs() 2.all.any() 3.bin.oct.hex.int() 4.bytes( ...
- [AGC057D] Sum Avoidance
Link 本篇题解大部分内容来自这篇文章 首先题意翻译: 给定一个正整数 \(S\) ,称一个正整数集合 \(A\) 是好的,当且仅当它满足以下条件: \(A\) 中元素在 \((0,S)\) 之间 ...
- BlockingQueue家族成员一览
最近在复习多线程的知识,必然少不了要扫描一遍JUC包下的各个类或接口,今天就先来聊一聊阻塞队列BlockingQueue: BlockingQueue是jdk1.5发布的JUC包下的一个工具类,他提供 ...
- docker中php xdebug调试开发
docker-compose环境来自:https://github.com/zhaojunlik...原文:http://blog.oeynet.com/post/9... 说明 在开发中,断点调试是 ...
- Spring Security(5)
您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来- 经常上网的人都应该有这样的体验:很多网站或者APP只需要第一次登录时输入用户名和密码之后,后面很长一段时间内就不需要再次输入密码了.这确实是一个 ...
- 如何禁止win7自动锁屏
前言 我是真的服了,就解决这个问题百度查了一大堆(浪费很长时间),都说是电源管理的问题,也不知道是谁抄谁的,改完还会自动锁屏. 然后我google一下子就解决了(这里有一个搜索技巧,就是将你的问题翻译 ...
- Apache Dubbo 多语言体系再添新员:首个 Rust 语言版本正式发布
Dubbo Rust 定位为 Dubbo 多语言体系的重要实现,提供高性能.易用.可扩展的 RPC 框架,同时通过接入 Dubbo Mesh 体系提供丰富的服务治理能力.本文主要为大家介绍 Dubbo ...
- 【SQL进阶】【分步写、联合各自排序、TIMESTAMPDIFF时间比较】Day04:多表查询
〇.内容 时间比较2-2 联合结果各自排序 查询列和GROUP BY 一.嵌套子查询 1.月均完成试卷数不小于3的用户爱作答的类别 自己的答案[错误]: SELECT tag, COUNT(A.sta ...