C++教程之lambda表达式一
什么是Lambda?
C++ 11增加了一个很重要的特性——Lambda表达式。营里(戴维营)的兄弟都对Objective-C很熟悉,很多人多block情有独钟,将各种回调函数、代理通通都用它来实现。甚至有人选择用FBKVOController、BlocksKit等开源框架将KVO、控件事件处理都改为通过block解决。原因就是简单、方便、直观,函数的定义和使用出如今同一个地方。这里的Lambda表达式实际上和block很类似,当然假设你用它和Swift语言的闭包比較,那就是一回事了。以下先看几个Lambda和block的演示样例代码。
1 .Objective-C的block演示样例代码,使用^
表示block类型,整体来说与函数指针的定义类似。
#import <Foundation/Foundation.h>
int main()
{
void (^block)() = ^void() {
NSLog(@"In block");
};
block();
return 0;
}
编译执行:
$ clang main.m -framework Foundation
$ ./a.out
2015-01-28 14:17:52.763 a.out[9901:165707] In block
2 .Swift的闭包,參数列表、返回值类型等都写在花括号{}
内部。
let closure = {
() -> Void in
println("In swift")
}
closure()
编译执行:
$ swiftc main.swift
$ ./main
In swift
測试Swift也能够直接使用Playground或REPL(Read-Eval-Print-Loop)环境。
3 .C++的Lambda表达式。
#include <iostream>
int main()
{
auto lambda = []() -> void{
std::cout << "In lambda" << std::endl;
};
lambda();
return 0;
}
编译执行,注意使用C++ 11的特性进行编译:
$ clang++ main.cpp -std=c++11
$ ./a.out
In lambda
Lambda、block实际上都是一个闭包(closure),它们都类似于一个匿名的函数,可是拥有捕获所在作用域中变量的能力;可以将函数做为对象一样使用。通经常使用它们来实现回调函数、代理等功能。
Lambda用法
1 .基本形式
语法 | 序号 |
---|---|
[ 捕获列表 |
(1) |
[ capture-list |
(2) |
[ capture-list |
(3) |
[ capture-list |
(4) |
- (1)为完整的形式,包括变量捕获列表、形參列表、可变属性(可选)和返回值类型等。
- (2)省略了mutable,表示Lambda不能改动捕获的变量。
- Lambda的返回值类型假设能够由函数体中的实际返回值推导出,能够省略。
- 假设没有形參,能够省略圆括号。
2 .捕获列表
lambda表达式中能够获取(捕获)它所在作用域中的变量值,而且有两种捕获方式:引用和值。我们能够在捕获列表中设置各变量的捕获方式。假设没有设置捕获列表,lambda默认不能捕获不论什么的变量,这点与block不同。
#include <iostream>
int main()
{
int a = 123;
auto lambda = []()->void{
std::cout << "In lambda: " << a << std::endl;
};
lambda();
return 0;
}
编译执行:
$ clang++ main.cpp -std=c++11
main.cpp:8:33: error: variable 'a' cannot be implicitly captured in a lambda
with no capture-default specified
std::cout << "In lambda: " << a << std::endl;
^
main.cpp:5:6: note: 'a' declared here
int a = 123;
^
main.cpp:7:16: note: lambda expression begins here
auto lambda = []()->void{
^
1 error generated.
在[]
中设置捕获列表,就能够在lambda中使用变量a
了,这里使用按值(=
,
by value)捕获。
#include <iostream>
int main()
{
int a = 123;
auto lambda = [=]()->void{
std::cout << "In lambda: " << a << std::endl;
};
lambda();
return 0;
}
编译执行:
$ clang++ main.cpp -std=c++11
$ ./a.out
In lambda: 123
捕获列表的设置方式:
|设置方式|结果| |-|-| |[]|不捕获| |[=]|所有按值捕获| |[&]|所有按引用捕获| |[a, b]|按值捕获变量a和b| |[&a, b]|按引用捕获a,按值捕获b| |[&, a]|按值捕获a,其他变量所有按引用捕获| |[=, &a]|按引用捕获a,其他所有按值捕获|
注意: 捕获列表没有先后顺序;捕获列表中的变量不能出现反复申明,比方
[&,
在
&a]&
中已经包括了&a
的申明了,因此不能再出现&a
。
详细的捕获类型,能够通过打印变量地址进行查看。
- 按值捕获:
auto lambda = [=]()->void{
std::cout << "In lambda: " << &a << std::endl;
};
执行结果为:
$ clang++ main.cpp -std=c++11
$ ./a.out
0x7fff555c69b8
In lambda: 0x7fff555c69b0
- 按引用捕获:
auto lambda = [&]()->void{
std::cout << "In lambda: " << &a << std::endl;
};
执行结果为:
$ clang++ main.cpp -std=c++11
$ ./a.out
0x7fff58a9b9b8
In lambda: 0x7fff58a9b9b8
3 .可变类型(mutable)
按值传递到lambda中的变量,默认是不可变的(immutable),假设须要在lambda中进行改动的话,须要在形參列表后加入mutable
keyword(按值传递无法改变lambda外变量的值)。
#include <iostream>
int main()
{
int a = 123;
std::cout << a << std::endl;
auto lambda = [=]() mutable ->void{
a = 234;
std::cout << "In lambda: " << a << std::endl;
};
lambda();
std::cout << a << std::endl;
return 0;
}
编译执行结果为:
$ clang++ main.cpp -std=c++11
lishan:c_study apple$ ./a.out
123
In lambda: 234 #能够改动
123 #注意这里的值,并没有改变
假设没有加入mutable
,则编译出错:
$ clang++ main.cpp -std=c++11
main.cpp:9:5: error: cannot assign to a variable captured by copy in a
non-mutable lambda
a = 234;
~ ^
1 error generated.
4 .返回值类型。
lambda的返回值类型能够省略,编译器会依据实际返回值的类型自己主动推导。
#include <iostream>
int main()
{
int a = 123;
std::cout << a << std::endl;
auto lambda = [=]() mutable{
a = 234;
std::cout << "In lambda: " << a << std::endl;
return a;
};
int b = lambda();
std::cout << b << std::endl;
return 0;
}
编译执行:
$ clang++ main.cpp -std=c++11
$ ./a.out
123
In lambda: 234
234
參考资料
- https://msdn.microsoft.com/en-us/library/dd293603.aspx
- http://www.oracle.com/technetwork/articles/servers-storage-dev/howto-use-lambda-exp-cpp11-2189895.html
- http://en.cppreference.com/w/cpp/language/lambda
- http://www.cprogramming.com/c++11/c++11-lambda-closures.html
本文档由长沙戴维营教育整理。
C++教程之lambda表达式一的更多相关文章
- Python函数式编程之lambda表达式
一:匿名函数的定义 lambda parameter_list: expression 二:三元表达式 条件为真时返回的结果 if 条件判断 else 条件为假的时候返回的结果 三:map map(f ...
- java函数式编程之lambda表达式
作为比较老牌的面向对象的编程语言java,在对函数式编程的支持上一直不温不火. 认为面向对象式编程就应该纯粹的面向对象,于是经常看到这样的写法:如果你想写一个方法,那么就必须把它放到一个类里面,然后n ...
- 12_Python的(匿名函数)Lambda表达式_Python编程之路
Python作为一门高级语言,与很多编程语言一样都具有匿名函数这一特征 匿名函数,也就Lambda表达式,通俗来讲就是不用命名的方法,直接定义,直接用即可 创建匿名函数需要用到Lambda关键字,下面 ...
- Pandas高级教程之:GroupBy用法
Pandas高级教程之:GroupBy用法 目录 简介 分割数据 多index get_group dropna groups属性 index的层级 group的遍历 聚合操作 通用聚合方法 同时使用 ...
- CRL快速开发框架系列教程二(基于Lambda表达式查询)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
- Tkinter教程之Text(1)篇
本文转载自:http://blog.csdn.net/jcodeer/article/details/1811343 '''Tkinter教程之Text篇(1)''''''1.创建第一个Text''' ...
- Java8一:Lambda表达式教程
1. 什么是λ表达式 λ表达式本质上是一个匿名方法.让我们来看下面这个例子: public int add(int x, int y) { return x + y; } 转成 ...
- Python爬虫与数据分析之进阶教程:文件操作、lambda表达式、递归、yield生成器
专栏目录: Python爬虫与数据分析之python教学视频.python源码分享,python Python爬虫与数据分析之基础教程:Python的语法.字典.元组.列表 Python爬虫与数据分析 ...
- λ(lambda)表达式
理论阶段 函数接口 函数接口是行为的抽象: 函数接口是数据转换器; java.util.Function包.定义了四个最基础的函数接口: Supplier<T>: 数据提供器,可以提供 T ...
随机推荐
- 【HTML5游戏开发小技巧】RPG情形对话中,令文本逐琢夸出
从前用JAVAscript完成过令文本逐琢夸出的效果,明天嗡炒用html5中的canvas完成一下.canvas里的内容可没有像<p>那样好操做,起首,您需求懂得一些html5的API才气 ...
- WPF 各种基础动画实现
C# using System; using System.Collections.Generic; using System.Linq; using System.Text; using Syste ...
- Python学习路径8——Python对象2
1.标准型运营商 1.1对象值对照 比较运算符用于如果相同类型的对象是相等.所有的内建类型的是在比较操作中支持,返回布尔比较操作值True 或 False. <span style=" ...
- 【Android进阶】在开发中Application到底用来做什么
首先,在一个Android程序中,有且只有一个Application对象,在程序开始跑起来的时候,首先执行Application的onCreate方法,这是一个Android应用的入口,在开发中,我们 ...
- Visual Prolog 的 Web 专家系统 (7)
GENI核心 -- 推理引擎(1)知识表示 GOAL最后一句是谓语infer(),它的含义是"论证". 因此,,进GENI核心,执行视图推理引擎. infer() infer(): ...
- [LeetCode]Palindrome Partitioning 找出所有可能的组合回文
给定一个字符串,切割字符串,这样每个子字符串是一个回文字符串. 要找出所有可能的组合. 办法:暴力搜索+回溯 class Solution { public: int *b,n; vector< ...
- HTML介绍JS
首先,该脚本的链接插入HTML代码: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvU2h1aVRpYW5OYWlMdW8=/font/5a6L5L2T/f ...
- Greenplum+Hadoop学习笔记-14-定义数据库对象之创建与管理模式
6.3.创建与管理模式 概述:DB内组织对象的一种逻辑结构.一个DB内能够有多个模式.在未指定模式时默认放置在public中.能够通过"\dn"方式查看数据库中现有模式: test ...
- ZOJ Problem Set - 2563 Long Dominoes 【如压力dp】
称号:ZOJ Problem Set - 2563 Long Dominoes 题意:给出1*3的小矩形.求覆盖m*n的矩阵的最多的不同的方法数? 分析:有一道题目是1 * 2的.比較火.链接:这里 ...
- 使用MySQL Workbench建立数据库,建立新的表,向表中添加数据
使用MySQL Workbench建立数据库,建立新的表,向表中添加数据 初学数据库,记录一下所学的知识.我用的MySQL数据库,使用MySQL Workbench管理.下面简单介绍一下如何使用MyS ...