C++ lambda函数说明

5 篇文章 0 订阅
4 篇文章 0 订阅

Lambda函数(C++11起)

 

C++

 

C++语言

 

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

语法

 
[ 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.

 本章尚未完成
原因:scope rules, capture list rules, nested lambdas, implicit capture vs odr use, decltype

例子

 

这个例子展示了(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'; 
}
#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

另请参阅

auto标识符表达一个由表达式定义的一个类型(C++11)[edit]

function

(C++11)

包装带有指定的函数调用签名的任何类型的可调用对象 

 

 
(类模板)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值