C++ lambda函数详解

c++中lambda函数是作为c++11新特新添加到c++中的,其主要是以匿名函数捕获scope内变量的方式构造闭包(closure)。相关标准参考:c++ reference
下面以若干不相干的简短程序的方式总结一下lambda的基本使用方式(暂未涉及lambda的c++17/20的特性)

[lambda.h]
#include
#pragma once
using namespace std;
void funcExt();
class Lamb{
    private:
        int aa =20;
        int bb =30;
    public:
        Lamb();
        ~Lamb();
        void show();
        void f(){
            auto fun10 = [this](){this->show();};
            fun10();
        }
};
---------------------------------------------------------------------------------------------------------
[lambda_ext.cpp]
#include "lambda.h"
auto func =[](){cout<<"funcExt result."<void funcExt(){
    func();
}
Lamb::Lamb(){};
Lamb::~Lamb(){};
void Lamb::show(){
    cout<// [ captures ] (optional)(C++20) (params) specifiers(optional) exception attr 
//              -> ret requires(optional)(C++20) { body }
      // tparams 模板形参列表,提供名称给泛型lambda的模板形参(c++20)
      // specifiers [mutable/constexpr(c++17)]
// [ captures ] ( params ) -> ret { body }
// [captures](params) { body }
// [ captures ] { body }
//      仅若不使用specifiers、exception、attr或ret之一才能使用此形式。

#include 
#include 
#include "lambda.h"

int ext = 10 ;

int main()
{
    // normal
    auto func1 = []() { cout << "func1:hello world." << endl; };
    func1();
    // var func1 type Z4mainE3$_1 ,only auto

    // ignore params
    auto func2 = [] { cout << "func2:haha." << endl; };
    func2();

    // spec ret
    auto func3 = []() -> int { return 1.0; };
    cout << "func3 ret:" << typeid(func3()).name() << "=" << func3() << endl;

    // mutil return spec ret
    auto func4 = [](int i) -> int {
      if(i>10) return 1;
      else return 2.3;
    };
    cout << "func4 ret:" << typeid(func4(5)).name() << "=" << func4(5) << endl;
    funcExt();

    // normal para_list lambda,compared to func9() and func7()
    int a=5,b=6;
    auto func5 = [](int& x,int& y){x++,y++;return x+y;};
    cout << "func5 sum:" << func5(a,b) << " a:" << a << " b:" << b << endl;
    // capture
    // capture opt: -- only capture non-static var
        // blank 不捕获任何变量
        // = 捕获外部作用域所有自动变量,按值传递给函数体,且包含this捕获,如果存在对象
        // & 捕获外部作用域所有自动变量,按引用传递给函数体,且包含this捕获,如果存在对象
        // this 按引用捕获当前对象
    {
      int c=7;
      {
        int e=9;
        {int f=11;/*static int ext=10;*/}
        auto func6 = [a, c, e, ext/*f*/]() { // capture f is illegal,not in lambda scope
                     // ext is static ,not captured, but capture list allowed -- warning
          cout<<"func6 a:"<" c:"<" e:"<" ext:"</*" f:"<endl;};
        func6();
      }
      auto func7 = [=,&a](){ // capture e is illegal,not in lambda scope
          cout<<"func7 a:"<" c:"</*" e:"<" ext:"</*c++;*/}; // var copy ,change not access
      func7();
      cout<<"a++: "<auto func8 = [](){
          cout<</*"a:"<"func8 ext:"<11;};
      func8();
      cout<<"access static ext+1: "<// lambda operator() is const(copy capture) , val capture non-modifiable
      auto func9 = [=]()mutable{
      c++;};
      cout<<"c: "<"func9 c++: "<// capture var copy
    }
    Lamb func;
    func.f();
    // diff between = and &
    auto func11 = [=](){return a;};
    cout<<"a: "<" func11 a++: "<auto func12 = [&](){return b;};
    cout<<"b: "<" func12 b++: "<1
func4 ret:i=2
funcExt result.
func5 sum:13 a:6 b:7
func6 a:6 c:7 e:9 ext:10
func7 a:6 c:7 ext:10
a++: 7
func8 ext:10
access static ext+1: 11
c: 7
func9 c++: 7
50
a: 7 func11 a++: 7
b: 7 func12 b++: 8

说明:
func1 – lambda基本用法,类型原因需要auto自动推到返回类型
func2 – 没有特殊用法比如限定符、异常等时,可以忽略圆括号用法
func3 – 指定lambda函数返回值
func4 – 多种不同类型返回值lambda函数时一定需要指定返回类型
func5 – 指定参数列表,以及对原始数据的修改情况,跟一般函数无异
func6 – 按变量复制的方式捕获scope内变量,需要注意的是,捕获变量只能是lambda作用域外的自动变量,f在作用域内,不能捕获、ext属于静态变量,本身不能被捕获,但是在捕获列表中捕获报错,gcc7.x编译仅仅warning,但是作为静态变量,是能够在lambda函数中直接访问的(但不是因为ext静态变量作用于整个项目,对比func8,虽然自动变量a,c,e在func8作用域之外,但没有指定捕获列表是不能直接访问的)
func7 – ①以全部捕获的方式对变量进行捕获 ②lambda默认为const成员函数,不能对按值传递的变量进行修改
func8 – 不指定任何捕获时,能过访问静态变量
func9 – 通过限定符mutable,使按值传递的变量能被修改,但因为是副本原因,能对变量进行修改,但修改对原数据并没有什么卵影响
func10、func11 – this捕获当前对象用法
func12 – 对比一下引用方式捕获跟按值捕获的小区别—-按值捕获在创建lambda时就将变量复制捕获,造成调用时数据内容产生延迟

你可能感兴趣的:(C)