Lambda函数(C++11起)

转载 2017年01月03日 00:55:16

构造一个闭包:能在作用域内捕获变量一个的匿名函数对象。

语法

 
[ capture ] ( params ) mutable exception attribute -> ret { body } (1)  
 
[ capture ] ( params ) -> ret { body } (2)  
 
[ capture ] ( params ) { body } (3)  
 
[ capture ] { body } (4)  
 

1) 完整的声明

2) 一个常lambda的声明:按副本捕获的对象不能被修改。

3) 省略后缀返回值类型:闭包的operator()的返回值类型是根据以下规则推导出的:

  • 如果body仅包含单一的return语句,那么返回值类型是返回表达式的类型(在此隐式转换之后的类型:右值到左值、数组与指针、函数到指针)
  • 否则,返回类型是void

4) 省略参数列表:函数没有参数,即参数列表是()

解释

mutable - 允许body修改传值进来的形参,以及调用它们的非常成员函数。
exception - 提供闭包类型的operator()成员函数的异常说明noexcept语句
attribute - 提供闭包类型的operator()成员函数的属性说明
capture - 指定哪些在函数声明处的作用域中可见的符号将在函数体内可见。

符号表可按如下规则传入:

  • [a,&b],按值捕获a,并按引用捕获b
  • [this],按值捕获了this指针
  • [&] 按引用捕获在lambda表达式所在函数的函数体中提及的全部自动储存持续性变量
  • [=] 按值捕获在lambda表达式所在函数的函数体中提及的全部自动储存持续性变量
  • [] 什么也没有捕获
params - 参数列表,与命名函数一样
ret - 返回值类型。如果不存在,它由该函数的return语句来隐式决定(或者是void,例如当它不返回任何值的时候)
body - 函数体


Lambda表达式构造唯一的匿名的非联合体非聚合体的匿名临时对象,叫做闭包型(ClosureType)。它有如下成员:

ClosureType::

operator()(params)

ret operator()(params) const { body }
  (关键字mutable没被使用)
ret operator()(params) { body }
  (关键字mutable被使用)
     

Executes the body of the lambda-expression, when invoked. When accessing a variable, accesses its captured copy (for the entities captured by copy), or the original object (for the entities captured by reference). Unless the keyword mutable was used in the lamda-expression, the objects that were captured by copy are non-modifiable from inside this operator().

Dangling references

If an entity is captured by reference, implicitly or explicitly, and the function call operator of the closure object is invoked after the entity's lifetime has ended, undefined behavior occurs. The C++ closures do not extend the lifetimes of the captured references.

ClosureType::

operator ret(*)(params)()

typedef ret(*F)(params);
operator F() const;
   
     

This member function is only defined if the capture list of the lambda-expression is empty.

The value returned by this conversion function is a function pointer that, when invoked, has the same effect as invoking the closure object's function call operator directly.

ClosureType::

ClosureType()

ClosureType() = delete;
   
ClosureType(const ClosureType& ) = default;
   
ClosureType(ClosureType&& ) = default;
   
     

Closure types are not DefaultConstructible. The copy constructor and the move constructor are implicitly-declared and may be implicitly-defined according to the usual rules for implicit 拷贝构造函数 and 移动的构造函数.

ClosureType::

operator=()

ClosureType& operator=(const ClosureType&) = delete;
   
     

Closure types are not CopyAssignable.

ClosureType::

~ClosureType()

~ClosureType() = default;
   
     

The destructor is implicitly-declared.

ClosureType::

CapturedParam

T1 a;

T2 b;

...
   
     

If the lambda-expression captures anything by copy (either implicitly with capture clause [=] or explicitly with a capture that does not include the character &, e.g. [a, b, c]), the closure type includes unnamed non-static data members, declared in unspecified order, that hold copies of all entities that were so captured.

The type of each data member is the type of the corresponding captured entity, except if the entity has reference type (in that case, references to functions are captured as-is, and references to objects are captured as copies of the referenced objects).

For the entities that are captured by reference (with the default capture [&] or when using the character &, e.g.[&a, &b, &c]), it is unspecified if additional data members are declared in the closure type.

例子

这个例子展示了(a)如何把一个lambda表达式放在通用的算法中,以及(b)lambda表达式得到的对象如何储存在std::function对象中。

#include <vector>
#include <iostream>
#include <algorithm>
#include <functional>
 
int main()
{
    std::vector<int> c { 1,2,3,4,5,6,7 };
    int x = 5;
    c.erase(std::remove_if(c.begin(), c.end(), [x](int n) { return n < x; } ), c.end());
 
    std::cout << "c: ";
    for (auto i: c) {
        std::cout << i << ' ';
    }
    std::cout << '\n';
 
    std::function<int (int)> func = [](int i) { return i+4; };
    std::cout << "func: " << func(6) << '\n'; 
}

输出:

c: 5 6 7
func: 10

相关文章推荐

C++ Primer : 第十章 : 泛型算法 之 lambda表达式和bind函数

lambda表达式和bind函数
  • JY_95
  • JY_95
  • 2015年08月18日 22:19
  • 677

C++ 11中关于Lambda表达式(匿名函数)

C++ 98/03 C++ 98/03标准并不原生支持匿名函数。不过可以利用Boost库的Boost.Lambda来实现一个匿名函数。...

C++ lambda表达式与函数对象

C++ lambda表达式与函数对象lambda表达式是C++11中引入的一项新技术,利用lambda表达式可以编写内嵌的匿名函数,用以替换独立函数或者函数对象,并且使代码更可读。但是从本质上来将,l...

【程序语言】C++ Lambda函数 的讨论

函数式编程的便利在Haskell的map中令人映象深刻,比如对一个列表 [1,2,3,4,5,6,7,8,9,10] 的所有元素实施+1操作只需要map(+1)[1..10] 就可以得到 =>...

lua闭包,ios block,C++lambda函数

下面是三篇描述这三种机制的文章, lua闭包,ios block,C++lambda函数

C++ Lambda表达式(还是比较习惯叫匿名函数)

不太情愿, 但不得不承认, 我是最近才知道Lambda这个词(前几天丢人丢大了), 这是作为一个程序猿的失职, 虽然很早以前就听说过"匿名函数"一词, 这里记下, 引以为戒. Lambda表达式, 又...

C++中Lambda函数

从软件开发的角度看,以lambda概念为基础的“函数式变成”(Functional Programming)是与命令式编程(Imperative Programming)、面向对象编程(Object-...

Lambda expression in C++ & Haskell || C++ 中的匿名函数 [EN/CN]

[EN]Simple exampleWell, lambda expression is very common technique that we should understand. Here’s...

Java 8 实战 - Lambda、流和函数式编程

  • 2017年03月08日 10:32
  • 12.98MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Lambda函数(C++11起)
举报原因:
原因补充:

(最多只允许输入30个字)