1.一个lambda表达式表示一个可调用的代码单元,可以理解为一个未命名的内联函数,但是与函数不同,lambda表达式可能定义在函数内部。其形式如下:

[capture list] (parameter list) -> return type { function body }

  • capture list 是一个lambda所在函数中定义的局部变量的列表(通常为空)
  • return type, parameter list 和 function body与任何普通函数一样,分别表示返回类型,参数列表和函数体
  • lambda必须使用尾置返回
  • 我们可以忽略参数列表和返回类型,但必须永远包含捕获列表和函数体
  • 如果忽略返回类型,lambda会从函数体推断出返回类型。
  • 如果lambda的函数体包含任何单一return语句之外的内容,且未指定返回类型,则返回void
  • 捕获列表只用于局部非static变量,lambda可以直接使用局部static变量和在它所在函数之外声明的名字。
void test()
{
int i = ;
int j = ;
auto f = [i, j](int base) -> int { return base + i + j; }; // i,j必须在捕获列表里面,这里的返回类型int其实可以省略
int k = f(); // k的结果为3
}

2.当定义一个lambda时,编译器生成一个与lambda对应的新的(未命名的)类类型。默认情况下这个类都包含一个对于该lambda所捕获的变量的数据成员。类似任何普通类的数据成员,lambda的数据成员也在lambda对象创建时被初始化。

3.与传值参数类似,采用值捕获的前提是变量可以拷贝,与参数不同,被捕获的变量的值是在lambda创建时拷贝,而不是调用时拷贝。

void test()
{
int i = ;
auto f = [i] {return i + ; }; // 此时i的值就已经被拷贝了
int j = f();
}

4.当以引用方式捕获一个变量时,必须保证在lambda执行时变量是存在的。

void test()
{
int i = ;
auto f = [&i] {return ++i; };
int j = f(); // 此时i等于11
}

5.在捕获列表中写一个 &或= 可以告诉编译器我们想采用值捕获还是引用捕获,这种方法叫做隐式捕获。

void test()
{
int i = ;
auto f = [&] {return ++i; }; // 采用引用捕获
int j = f();
}

6.我们也可以混合使用值捕获或者引用捕获。当使用混合方式的时候,显示捕获的方式不可以与隐式捕获的方式相同。

void test()
{
int i = ;
int j = ;
auto f = [=, &i] {i++; return i + j; }; // i采用引用捕获,其他采用值捕获
int k = f(); // k等于20
}

7.默认情况下,对于一个值被拷贝的变量,lambda不会改变其值,如果我们希望能改变一个被捕获的变量的值,就必须在参数列表首加上mutable。

void test()
{
int i = ;
auto f = [i] (){return ++i; }; // 错误,不可以改变i的值
auto f1 = [i] () mutable {return ++i; }; // 正确
}

8.bind函数(头文件 functional中)可以看作一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来适应原对象的参数列表。调用bind的一般形式为:

auto newCallable = bind(callable, arg);

void test(int i, int j)
{
std::cout << i - j << std::endl;
} auto test0 = std::bind(test, , );
test0(); // 结果4 auto test1 = std::bind(test, std::placeholders::_1, , std::placeholders::_2, ); // 错误,不可以这么写
test1(); auto test2 = std::bind(test, std::placeholders::_1, );
test2(); // 结果-4 auto test3 = std::bind(test, std::placeholders::_1, std::placeholders::_2);
test3(, ); // 结果1 auto test4 = std::bind(test, std::placeholders::_2, std::placeholders::_1); // 参数顺序可以重排
test4(, ); // 结果-1 auto test5 = std::bind(test, , std::placeholders::_1); // 注意这个占位符占的是test5()的参数位置,而不是test()的
test5(); // 结果-4

以上代码请注意命名空间,否则会和socket的bind函数产生二义性。

9.如果我们想绑定的参数无法拷贝,或者我们想引用时应该使用ref函数。

void test(int& i, int j)
{
std::cout << i - j << std::endl;
} int i = ;
auto test0 = std::bind(test, std::ref(i), );
test0(); // 结果4

10.编译器将lambda表达式翻译成一个未命名类的未命名对象,在lambda表达式产生的类中含有一个重载的函数调用运算符。这个类不含默认构造函数,赋值运算符及默认析构函数。它是否有默认的拷贝/移动构造函数则通常要视捕获的数据成员类型而定。

std::size_t i;
auto test_func = [i](const std::string& str) {return str.size() > i; }; class test
{
public:
test(std::size_t size) : m_size(size) {}
bool operator()(const std::string& str) { return str.size() > m_size; }; private:
std::size_t m_size;
};

C++ Primer 笔记——lambda表达式的更多相关文章

  1. Java8学习笔记----Lambda表达式 (转)

    Java8学习笔记----Lambda表达式 天锦 2014-03-24 16:43:30 发表于:ATA之家       本文主要记录自己学习Java8的历程,方便大家一起探讨和自己的备忘.因为本人 ...

  2. .net学习笔记---lambda表达式(自执行方法)

    http://www.cnblogs.com/jesse2013/p/happylambda.html#b034 lambda表达式 http://www.cnblogs.com/OceanEyes/ ...

  3. Java学习笔记-Lambda表达式

    Lambda表达式支持将代码块作为方法参数,Lambda表达式允许使用简洁的代码来创建只有一个抽象方法的接口(这种接口被称为函数是接口)的实例 意义 自从Java 8开始,Java支持Lambda表达 ...

  4. Java疯狂讲义笔记——Lambda表达式

    Java8新增的Lambda表达式 [特性]支持将代码块作为方法参数,Lambda表达式允许使用更简洁的代码来创建只有一个抽象方法的接口(这种接口被称为函数式接口)的实例. [组成部分]1,形参列表 ...

  5. 0028 Java学习笔记-面向对象-Lambda表达式

    匿名内部类与Lambda表达式示例 下面代码来源于:0027 Java学习笔记-面向对象-(非静态.静态.局部.匿名)内部类 package testpack; public class Test1{ ...

  6. 委托学习笔记后续:泛型委托及委托中所涉及到匿名方法、Lambda表达式

    引言: 最初学习c#时,感觉委托.事件这块很难,其中在学习的过程中还写了一篇学习笔记:委托.事件学习笔记.今天重新温故委托.事件,并且把最近学习到和委托相关的匿名方法.Lambda表达式及泛型委托记录 ...

  7. 《C#本质论》读书笔记(12)委托和Lambda表达式

    12.1.委托概述 12.1.2 委托的数据类型 为了减少重复代码数量,可以将比较方法作为参数传递给 BubbleSort()方法.此外,为了将方法作为参数传递,必须有一个能够标识方法的数据类型--也 ...

  8. Java开发笔记(六十一)Lambda表达式

    前面介绍了匿名内部类的简单用法,通过在sort方法中运用匿名内部类,不但能够简化代码数量,还能保持业务代码的连续性.只是匿名内部类的结构仍显啰嗦,虽然它省去了内部类的名称,但是花括号里面的方法定义代码 ...

  9. lambda表达式笔记

    前几天一位好友分享了一篇文章,其中讲到了lambda表达式,正好最近看了一些内容,就做做笔记吧... lambda表达式服务于函数式接口,如果需要一个函数式接口的对象时,就可以用lambda表达式代替 ...

随机推荐

  1. Android逆向基础----Android Dalvik虚拟机

    Android Dalvik虚拟机的特点: l  体积小,占用内存空间小. l  专有DEX可执行文件. l  常量池采用32位索引值,寻址类方法名,字段名,常量更快. l  基于寄存器架构,并拥有一 ...

  2. wx小程序-音频视频!

    1.音乐的启动跟暂停 dom里面图片切换的另一种方法 通过变量 改变路径 2.监听 在onload里面 3.定义了一个全局变量 然后在但页面中获取 app.js 单页面中 app.js 的三个生命周期

  3. linux(ubuntu) python 版本切换

    参考链接:https://blog.csdn.net/thankyou0/article/details/79610854

  4. Django实战(一)-----用户登录与注册系统5(图片验证码)

    为了防止机器人频繁登录网站或者破坏分子恶意登录,很多用户登录和注册系统都提供了图形验证码功能. 验证码(CAPTCHA)是一种区分用户是计算机还是人的公共全自动程序. 可以防止恶意破解密码.刷票.论坛 ...

  5. 读Java并发编程实践中,向已有线程安全类添加功能--客户端加锁实现示例

    在Java并发编程实践中4.4中提到向客户端加锁的方法.此为验证示例,写的不好,但可以看出结果来. package com.blackbread.test; import java.util.Arra ...

  6. 记一次手动SQL注入

    1.检测到可能存在注入漏洞的url 最常用的 ' ,and 1=1 ,and 1=2 http://www.xxx.com/subcat.php?id=1 2.判断字段个数 http://www.xx ...

  7. 设计模式C++学习笔记之七(AbstractFactory抽象工厂模式)

      抽象工厂,提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类.对于工厂方法来说,抽象工厂可实现一系列产品的生产,抽象工厂更注重产品的组合. 看代码: 7.1.解释 main(),女 ...

  8. POJ3580 SuperMemo splay伸展树,区间操作

    题意:实现一种数据结构,支持对一个数列的 6 种操作:第 x 个数到第 y 个数之间的数每个加 D:第 x 个数到第 y 个数之间全部数翻转:第 x 个数到第 y 个数之间的数,向后循环流动 c 次, ...

  9. js声明引入和变量声明和变量类型、变量

    问题: 在网页的发展历程中,发现网页不能对用户的数据进行自动校验,和提供一些特效. 解决: 使用javascript. 作用 可以让网页和用户进行直接简单的交互. 可以让网页制作特效和动画. 声明js ...

  10. 第八次作业(课堂实战)- 项目UML设计(团队)

    1. 团队信息 队名:小白吃队 成员: 后敬甲 031602409 卢泽明 031602328 蔡文斌 031602301 葛亮 031602617 刘浩 031602423 黄泽 031602317 ...