c11新特性中加入了lambda表达式,所以Qt 也支持

需在.pro文件中加入

CONFIG += c++11例子:

 1    QString program = "C:/Windows/System32/cmd.exe";2     QStringList arguments;3     arguments << "/c" << "dir" << "C:\\";4     QProcess* cmdProcess = new QProcess;5     QObject::connect(cmdProcess, &QProcess::readyRead,[=](){6         QTextCodec *codec = QTextCodec::codecForName("GBK");7         QString dir = codec->toUnicode(cmdProcess->readAll());8         qDebug() << dir;9     });
10     cmdProcess->start(program, arguments);


一段简单的Code


我也不是文艺的人,对于Lambda的历史,以及Lambda与C++的那段渊源,我也不是很熟悉,技术人,讲究拿代码说事。


复制代码 代码如下:


#include<iostream>
using namespace std;

int main()
{
int a = 1;
int b = 2;

auto func = [=, &b](int c)->int {return b += a + c;};
return 0;
}



当我第一次看到这段代码时,我直接凌乱了,直接看不懂啊。上面这段代码,如果你看懂了,下面的内容就当时复习了;如果看不懂了,就接着和我一起总结吧。


基本语法


简单来说,Lambda函数也就是一个函数,它的语法定义如下:


复制代码 代码如下:


[capture](parameters) mutable ->return-type{statement}



1.[capture]:捕捉列表。捕捉列表总是出现在Lambda函数的开始处。实际上,[]是Lambda引出符。编译器根据该引出符判断接下来的代码是否是Lambda函数。捕捉列表能够捕捉上下文中的变量以供Lambda函数使用;


2.(parameters):参数列表。与普通函数的参数列表一致。如果不需要参数传递,则可以连同括号“()”一起省略;


3.mutable:mutable修饰符。默认情况下,Lambda函数总是一个const函数,mutable可以取消其常量性。在使用该修饰符时,参数列表不可省略(即使参数为空);


4.->return-type:返回类型。用追踪返回类型形式声明函数的返回类型。我们可以在不需要返回值的时候也可以连同符号”->”一起省略。此外,在返回类型明确的情况下,也可以省略该部分,让编译器对返回类型进行推导;


5.{statement}:函数体。内容与普通函数一样,不过除了可以使用参数之外,还可以使用所有捕获的变量。


与普通函数最大的区别是,除了可以使用参数以外,Lambda函数还可以通过捕获列表访问一些上下文中的数据。具体地,捕捉列表描述了上下文中哪些数据可以被Lambda使用,以及使用方式(以值传递的方式或引用传递的方式)。语法上,在“[]”包括起来的是捕捉列表,捕捉列表由多个捕捉项组成,并以逗号分隔。捕捉列表有以下几种形式:


1.[var]表示值传递方式捕捉变量var;
2.[=]表示值传递方式捕捉所有父作用域的变量(包括this);
3.[&var]表示引用传递捕捉变量var;
4.[&]表示引用传递方式捕捉所有父作用域的变量(包括this);
5.[this]表示值传递方式捕捉当前的this指针。


上面提到了一个父作用域,也就是包含Lambda函数的语句块,说通俗点就是包含Lambda的“{}”代码块。上面的捕捉列表还可以进行组合,例如:


1.[=,&a,&b]表示以引用传递的方式捕捉变量a和b,以值传递方式捕捉其它所有变量;
2.[&,a,this]表示以值传递的方式捕捉变量a和this,引用传递方式捕捉其它所有变量。


不过值得注意的是,捕捉列表不允许变量重复传递。下面一些例子就是典型的重复,会导致编译时期的错误。例如:


3.[=,a]这里已经以值传递方式捕捉了所有变量,但是重复捕捉a了,会报错的;
4.[&,&this]这里&已经以引用传递方式捕捉了所有变量,再捕捉this也是一种重复。


Lambda的使用


对于Lambda的使用,说实话,我没有什么多说的,个人理解,在没有Lambda之前的C++ , 我们也是那样好好的使用,并没有对缺少Lambda的C++有什么抱怨,而现在有了Lambda表达式,只是更多的方便了我们去写代码。不知道大家是否记得C++ STL库中的仿函数对象,仿函数想对于普通函数来说,仿函数可以拥有初始化状态,而这些初始化状态是在声明仿函数对象时,通过参数指定的,一般都是保存在仿函数对象的私有变量中;在C++中,对于要求具有状态的函数,我们一般都是使用仿函数来实现,比如以下代码:


复制代码 代码如下:


#include<iostream>
using namespace std;

typedef enum
{
add = 0,
sub,
mul,
divi
}type;

class Calc
{
public:
Calc(int x, int y):m_x(x), m_y(y){}

int operator()(type i)
{
switch (i)
{
case add:
return m_x + m_y;
case sub:
return m_x - m_y;
case mul:
return m_x * m_y;
case divi:
return m_x / m_y;
}
}

private:
int m_x;
int m_y;
};

int main()
{
Calc addObj(10, 20);
cout<<addObj(add)<<endl; // 发现C++11中,enum类型的使用也变了,更“强”了
return 0;
}



现在我们有了Lambda这个利器,那是不是可以重写上面的实现呢?看代码:


复制代码 代码如下:


#include<iostream>
using namespace std;

typedef enum
{
add = 0,
sub,
mul,
divi
}type;

int main()
{
int a = 10;
int b = 20;

auto func = [=](type i)->int {
switch (i)
{
case add:
return a + b;
case sub:
return a - b;
case mul:
return a * b;
case divi:
return a / b;
}
};

cout<<func(add)<<endl;
}



显而易见的效果,代码简单了,你也少写了一些代码,也去试一试C++中的Lambda表达式吧。


关于Lambda那些奇葩的东西


看以下一段代码:


复制代码 代码如下:


#include<iostream>
using namespace std;

int main()
{
int j = 10;
auto by_val_lambda = [=]{ return j + 1; };
auto by_ref_lambda = [&]{ return j + 1; };
cout<<"by_val_lambda: "<<by_val_lambda()<<endl;
cout<<"by_ref_lambda: "<<by_ref_lambda()<<endl;

++j;
cout<<"by_val_lambda: "<<by_val_lambda()<<endl;
cout<<"by_ref_lambda: "<<by_ref_lambda()<<endl;

return 0;
}



程序输出结果如下:


复制代码 代码如下:


by_val_lambda: 11
by_ref_lambda: 11
by_val_lambda: 11
by_ref_lambda: 12


你想到了么???那这又是为什么呢?为什么第三个输出不是12呢?


在by_val_lambda中,j被视为一个常量,一旦初始化后不会再改变(可以认为之后只是一个跟父作用域中j同名的常量),而在by_ref_lambda中,j仍然在使用父作用域中的值。所以,在使用Lambda函数的时候,如果需要捕捉的值成为Lambda函数的常量,我们通常会使用按值传递的方式捕捉;相反的,如果需要捕捉的值成成为Lambda函数运行时的变量,则应该采用按引用方式进行捕捉。


再来一段更晕的代码:


复制代码 代码如下:


#include<iostream>
using namespace std;

int main()
{
int val = 0;
// auto const_val_lambda = [=](){ val = 3; }; wrong!!!

auto mutable_val_lambda = [=]() mutable{ val = 3; };
mutable_val_lambda();
cout<<val<<endl; // 0

auto const_ref_lambda = [&]() { val = 4; };
const_ref_lambda();
cout<<val<<endl; // 4

auto mutable_ref_lambda = [&]() mutable{ val = 5; };
mutable_ref_lambda();
cout<<val<<endl; // 5

return 0;
}



这段代码主要是用来理解Lambda表达式中的mutable关键字的。默认情况下,Lambda函数总是一个const函数,mutable可以取消其常量性。按照规定,一个const的成员函数是不能在函数体内修改非静态成员变量的值。例如上面的Lambda表达式可以看成以下仿函数代码:


复制代码 代码如下:


class const_val_lambda
{
public:
const_val_lambda(int v) : val(v) {}
void operator()() const { val = 3; } // 常量成员函数

private:
int val;
};



对于const的成员函数,修改非静态的成员变量,所以就出错了。而对于引用的传递方式,并不会改变引用本身,而只会改变引用的值,因此就不会报错了。都是一些纠结的规则。慢慢理解吧。

Qt5中使用lambda表达式相关推荐

  1. Python中的Lambda表达式

    Lambda表达式 (Lambda Expressions) Lambda Expressions are ideally used when we need to do something simp ...

  2. 什么是C ++ 11中的lambda表达式?

    本文翻译自:What is a lambda expression in C++11? What is a lambda expression in C++11? 什么是C ++ 11中的lambda ...

  3. C++中的Lambda表达式详解

    函数对象与Lambdas 你编写代码时,尤其是使用 STL 算法时,可能会使用函数指针和函数对象来解决问题和执行计算.函数指针和函数对象各有利弊.例如,函数指针具有最低的语法开销,但不保持范围内的状态 ...

  4. android studio lambda插件,在Android Studio中使用Lambda表达式(retrolambda)

    在Android Studio中使用Lambda表达式 要在Android Studio中使用Lambda表达式,需要借助一个gradle插件来完成. A gradle plugin for gett ...

  5. nashorn预编译_Java 8:在新的Nashorn JS引擎中编译Lambda表达式

    nashorn预编译 在最近的一篇文章中,我了解了Java 8和Scala如何实现Lambda表达式. 众所周知,Java 8不仅引入了对Javac编译器的改进,而且还引入了全新的解决方案-Nasho ...

  6. Java 8:在新的Nashorn JS引擎中编译Lambda表达式

    在最近的一篇文章中,我了解了Java 8和Scala如何实现Lambda表达式. 众所周知,Java 8不仅引入了对Javac编译器的改进,而且还引入了全新的解决方案-Nashorn. 这个新引擎旨在 ...

  7. Java 8中使用Lambda表达式的策略模式

    策略模式是" 设计模式:可重用对象的元素"书中的模式之一 . 本书所述的策略模式的意图是: 定义一系列算法,封装每个算法,并使它们可互换. 策略使算法独立于使用该算法的客户端而变化 ...

  8. 使用NetBeans Lambda支持在Java 8中使用Lambda表达式对列表进行排序

    作为JSR 335的一部分, Lambda表达式已从Java 8开始引入Java语言,这是Java语言的一个重大变化. 如果您想了解更多关于Lambda表达式以及JSR 335的信息,可以访问以下资源 ...

  9. 如何开始使用Java中的Lambda表达式

    by Luis Santiago 路易斯·圣地亚哥(Luis Santiago) 如何开始使用Java中的Lambda表达式 (How to start working with Lambda Exp ...

最新文章

  1. eclipse静态部署tomcat
  2. Java基本类型和取值范围
  3. Ancient China Story of Shen-《Kung Fu Panda 2》
  4. 网易云信3.3.0版本更新啦!
  5. docker 安装hadoop
  6. vmw6.5安装Freebsd8.1桌面gnome
  7. win7 IE9 internet explorer[IE] [IE 9]已停止工作
  8. python颜色表_Python:数据可视化,必须注意的30个小技巧
  9. 簡單設定 kernel 選項在使用 iptables 前
  10. 安装软件,竟然把UOS装崩溃了
  11. 通过QQ查看对方的ip地址
  12. Unity中,图片 替换 光标 —— 疑问解答
  13. Ruby程序语言入门
  14. mindoc升级总结
  15. 2022年,4款值得用的报表工具软件推荐!
  16. #SVN Skipped ‘xxx‘ -- Node remains in conflict 错误的解决办法#
  17. Oracle中用户查询表一定要加上表空间名的问题
  18. 产品模块化设计的前世今生
  19. 推荐四个不错的公众号
  20. 取模、乘法和除法运算在CPU和GPU上的效率

热门文章

  1. 时寒冰 --- 一如即往的支持你
  2. 搭建表白墙 公众号_韶大表白墙 第十季 第75期 | 篮球共青杯决赛体教1班穿黑色衣服的0号...
  3. C++ 鼠标模拟程序
  4. ZBrush中常用3D笔触效果
  5. linux can总线接收数据串口打包上传_USART串口通讯
  6. 三年打造AI芯片黑科技,IBM“狩猎女神之矛”将撬动企业混合云
  7. 让自己的app支持小程序
  8. TOP100summit分享实录 | 如何构建一套全链路的故障追踪和故障自愈系统?
  9. java-----Map
  10. 甲骨文中国良心裁员:首批900人,赔偿N+6