C++lambda関数の詳細

8612 ワード

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

説明:func 1–lambdaの基本的な使い方.タイプの原因は自動的に戻りタイプfunc 2にプッシュする必要がある-限定子、異常などの特別な使い方がない場合、カッコの使い方func 3を無視することができます–lambda関数の戻り値func 4を指定する–複数の異なるタイプの戻り値lambda関数の場合、必ず戻りタイプfunc 5を指定する必要があります–パラメータリストを指定します.また、元のデータの変更については、一般関数と変わらないfunc 6–scope内の変数を変数コピーでキャプチャするが、キャプチャ変数はlambdaの作用域外の自動変数のみであり、fは作用域内ではキャプチャできず、extは静的変数に属し、本体はキャプチャできないが、キャプチャリストではキャプチャエラー、gcc 7.xコンパイルはwarningのみですが、静的変数として、lambda関数で直接アクセスできる(ただし、ext静的変数がプロジェクト全体に作用するためではなく、func 8と比較すると、自動変数a,c,eはfunc 8の役割ドメイン外であるが、キャプチャリストを指定していないと直接アクセスできない)func 7–①変数をすべてキャプチャする②lambdaはconstメンバー関数としてデフォルトであり、値で渡された変数を修正することはできないfunc 8–キャプチャを指定しない取得時、静的変数func 9にアクセスすることができます–修飾子mutableによって、値で伝達される変数を修正することができますが、コピーの原因で変数を修正することができますが、修正は元のデータに対してfunc 10に影響を与えません.func 11–this現在のオブジェクトのキャプチャ使用法func 12–参照方式のキャプチャと値によるキャプチャの小さな違いを比較します.-値によるキャプチャlambdaの作成時に変数をコピーしてキャプチャし、呼び出し時にデータコンテンツが遅延する