web-dev-qa-db-de.com

Was ist ein Lambda-Ausdruck in C ++ 11?

Was ist ein Lambda-Ausdruck in C++ 11? Wann würde ich eins benutzen? Welche Klasse von Problemen lösen sie, die vor ihrer Einführung nicht möglich waren?

Ein paar Beispiele und Anwendungsfälle wären nützlich.

1376
Nawaz

Das Problem

C++ enthält nützliche generische Funktionen wie std::for_each und std::transform, was sehr praktisch sein kann. Leider können sie auch recht umständlich zu bedienen sein, insbesondere wenn der Funktor , den Sie anwenden möchten, für die jeweilige Funktion eindeutig ist.

#include <algorithm>
#include <vector>

namespace {
  struct f {
    void operator()(int) {
      // do something
    }
  };
}

void func(std::vector<int>& v) {
  f f;
  std::for_each(v.begin(), v.end(), f);
}

Wenn Sie f nur einmal an dieser Stelle verwenden, scheint es übertrieben, eine ganze Klasse zu schreiben, nur um etwas Triviales und Einmaliges zu tun.

In C++ 03 könnten Sie versucht sein, etwas wie das Folgende zu schreiben, um den Funktor lokal zu halten:

void func2(std::vector<int>& v) {
  struct {
    void operator()(int) {
       // do something
    }
  } f;
  std::for_each(v.begin(), v.end(), f);
}

dies ist jedoch nicht zulässig. f kann in C++ 03 nicht an eine template -Funktion übergeben werden.

Die neue Lösung

C++ 11 führt Lambdas ein, mit denen Sie einen anonymen Inline-Funktor schreiben können, der den struct f ersetzt. Für kleine einfache Beispiele kann dies übersichtlicher zu lesen sein (alles an einem Ort aufbewahren) und möglicherweise einfacher zu warten sein, zum Beispiel in der einfachsten Form:

void func3(std::vector<int>& v) {
  std::for_each(v.begin(), v.end(), [](int) { /* do something here*/ });
}

Lambda-Funktionen sind nur syntaktischer Zucker für anonyme Funktoren.

Rückgabetypen

In einfachen Fällen wird der Rückgabetyp des Lambdas für Sie abgeleitet, z.

void func4(std::vector<double>& v) {
  std::transform(v.begin(), v.end(), v.begin(),
                 [](double d) { return d < 0.00001 ? 0 : d; }
                 );
}

wenn Sie jedoch anfangen, komplexere Lambdas zu schreiben, werden Sie schnell auf Fälle stoßen, in denen der Rückgabetyp vom Compiler nicht abgeleitet werden kann, z.

void func4(std::vector<double>& v) {
    std::transform(v.begin(), v.end(), v.begin(),
        [](double d) {
            if (d < 0.0001) {
                return 0;
            } else {
                return d;
            }
        });
}

Um dies zu beheben, können Sie explizit einen Rückgabetyp für eine Lambda-Funktion angeben, indem Sie -> T verwenden:

void func4(std::vector<double>& v) {
    std::transform(v.begin(), v.end(), v.begin(),
        [](double d) -> double {
            if (d < 0.0001) {
                return 0;
            } else {
                return d;
            }
        });
}

Variablen "erfassen"

Bisher haben wir nichts anderes verwendet als das, was an das Lambda darin übergeben wurde, aber wir können auch andere Variablen innerhalb des Lambdas verwenden. Wenn Sie auf andere Variablen zugreifen möchten, können Sie die Capture-Klausel (den [] des Ausdrucks) verwenden, die in diesen Beispielen bisher nicht verwendet wurde, z.

void func5(std::vector<double>& v, const double& epsilon) {
    std::transform(v.begin(), v.end(), v.begin(),
        [epsilon](double d) -> double {
            if (d < epsilon) {
                return 0;
            } else {
                return d;
            }
        });
}

Sie können sowohl nach Referenz als auch nach Wert erfassen, die Sie mit & bzw. = angeben können:

  • [&epsilon] Nach Referenz erfassen
  • [&] erfasst alle im Lambda verwendeten Variablen als Referenz
  • [=] erfasst alle im Lambda verwendeten Variablen nach Wert
  • [&, epsilon] erfasst Variablen wie mit [&], aber in Epsilon nach Wert
  • [=, &epsilon] erfasst Variablen wie mit [=], aber Epsilon als Referenz

Die generierte operator() ist standardmäßig const, mit der Konsequenz, dass die Erfassung const ist, wenn Sie standardmäßig darauf zugreifen. Dies hat zur Folge, dass jeder Aufruf mit derselben Eingabe dasselbe Ergebnis erzeugt. Sie können jedoch das Lambda als mutable markieren anfordern, dass die erzeugte operator() nicht erzeugt wird const.

1393
Flexo

Was ist eine Lambda-Funktion?

Das C++ - Konzept einer Lambda-Funktion entspringt der Lambda-Rechnung und der funktionalen Programmierung. Ein Lambda ist eine unbenannte Funktion, die (in der tatsächlichen Programmierung, nicht in der Theorie) für kurze Code-Schnipsel nützlich ist, die nicht wiederverwendet werden können und deren Benennung nicht wert ist.

In C++ ist eine Lambda-Funktion wie folgt definiert

[]() { } // barebone lambda

oder in seiner ganzen Pracht

[]() mutable -> T { } // T is the return type, still lacking throw()

[] ist die Erfassungsliste, () die Argumentliste und {} der Funktionskörper.

Die Erfassungsliste

Die Erfassungsliste definiert, was von außerhalb des Lambdas innerhalb des Funktionskörpers verfügbar sein soll und wie. Es kann entweder sein:

  1. ein Wert: [x]
  2. eine Referenz [& x]
  3. beliebige Variable, die sich derzeit im Gültigkeitsbereich befindet (Referenz [&])
  4. wie 3, aber nach Wert [=]

Sie können eines der oben genannten Elemente in einer durch Kommas getrennten Liste [x, &y] mischen.

Die Argumentliste

Die Argumentliste ist dieselbe wie in jeder anderen C++ - Funktion.

Der Funktionskörper

Der Code, der ausgeführt wird, wenn das Lambda tatsächlich aufgerufen wird.

Rückgabetyp Abzug

Wenn ein Lambda nur eine return-Anweisung hat, kann der return-Typ weggelassen werden und hat den impliziten Typ decltype(return_statement).

Veränderlich

Wenn ein Lambda als veränderlich markiert ist (z. B. []() mutable { }), darf es die von value erfassten Werte ändern.

Anwendungsfälle

Die durch den ISO-Standard definierte Bibliothek profitiert stark von Lambdas und erhöht die Benutzerfreundlichkeit um einige Balken, da Benutzer ihren Code jetzt nicht mehr mit kleinen Funktoren in einem zugänglichen Bereich überladen müssen.

C++ 14

In C++ 14 wurden Lambdas um verschiedene Vorschläge erweitert.

Initialisierte Lambda-Erfassungen

Ein Element der Erfassungsliste kann jetzt mit = initialisiert werden. Dies ermöglicht das Umbenennen von Variablen und das Erfassen durch Verschieben. Ein Beispiel aus der Norm:

int x = 4;
auto y = [&r = x, x = x+1]()->int {
            r += 2;
            return x+2;
         }();  // Updates ::x to 6, and initializes y to 7.

und eine aus Wikipedia, die zeigt, wie man mit std::move aufnimmt:

auto ptr = std::make_unique<int>(10); // See below for std::make_unique
auto lambda = [ptr = std::move(ptr)] {return *ptr;};

Generisches Lambdas

Lambdas können jetzt generisch sein (auto wäre hier gleichbedeutend mit T, wenn T ein Typvorlagenargument irgendwo im umgebenden Bereich wäre):

auto lambda = [](auto x, auto y) {return x + y;};

Verbesserter Abzug von Rückgabetypen

C++ 14 erlaubt für jede Funktion abgeleitete Rückgabetypen und beschränkt sie nicht auf Funktionen der Form return expression;. Dies gilt auch für Lambdas.

797
pmr

Lambda-Ausdrücke werden normalerweise verwendet, um Algorithmen so zu kapseln, dass sie an eine andere Funktion übergeben werden können. Jedoch ist es ist möglich, ein Lambda sofort nach der Definition auszuführen:

[&](){ ...your code... }(); // immediately executed lambda expression

ist funktional äquivalent zu

{ ...your code... } // simple code block

Dies macht Lambda-Ausdrücke ein leistungsfähiges Werkzeug zum Umgestalten komplexer Funktionen. Sie beginnen, indem Sie einen Codeabschnitt wie oben gezeigt in eine Lambda-Funktion einschließen. Der Prozess der expliziten Parametrisierung kann dann schrittweise mit Zwischentests nach jedem Schritt durchgeführt werden. Sobald Sie den Code-Block vollständig parametrisiert haben (wie durch das Entfernen des & gezeigt), können Sie den Code an einen externen Ort verschieben und ihn zu einer normalen Funktion machen.

Ebenso können Sie Lambda-Ausdrücke verwenden, um Variablen basierend auf dem Ergebnis eines Algorithmus zu initialisieren ...

int a = []( int b ){ int r=1; while (b>0) r*=b--; return r; }(5); // 5!

Als eine Art, Ihre Programmlogik zu partitionieren, könnten Sie es sogar nützlich finden, einen Lambda-Ausdruck als Argument an einen anderen Lambda-Ausdruck zu übergeben ...

[&]( std::function<void()> algorithm ) // wrapper section
   {
   ...your wrapper code...
   algorithm();
   ...your wrapper code...
   }
([&]() // algorithm section
   {
   ...your algorithm code...
   });

Mit Lambda-Ausdrücken können Sie auch benannte verschachtelte Funktionen erstellen, um doppelte Logik zu vermeiden. Die Verwendung von benannten Lambdas ist im Vergleich zu anonymen Inline-Lambdas etwas augenschonender, wenn eine nicht-triviale Funktion als Parameter an eine andere Funktion übergeben wird. Hinweis: Vergessen Sie nicht das Semikolon nach der schließenden geschweiften Klammer.

auto algorithm = [&]( double x, double m, double b ) -> double
   {
   return m*x+b;
   };

int a=algorithm(1,2,3), b=algorithm(4,5,6);

Wenn bei der anschließenden Profilerstellung ein erheblicher Initialisierungsaufwand für das Funktionsobjekt auftritt, können Sie dies als normale Funktion neu schreiben.

164
nobar

Antworten

F: Was ist ein Lambda-Ausdruck in C++ 11?

A: Unter der Haube ist es das Objekt einer automatisch generierten Klasse mit Überladung operator () const. Ein solches Objekt heißt closure und wird vom Compiler erstellt. Dieses "Closure" -Konzept kommt dem Bind-Konzept von C++ 11 sehr nahe. Aber Lambdas generieren normalerweise besseren Code. Und Anrufe durch Schließungen ermöglichen ein vollständiges Inlining.

F: Wann würde ich eine verwenden?

A: Um "einfache und kleine Logik" zu definieren und den Compiler zu fragen, führen Sie die Generierung anhand der vorherigen Frage durch. Sie geben einem Compiler einige Ausdrücke, die Sie in operator () verwenden möchten. Alle anderen Sachen, die der Compiler für Sie generiert.

F: Welche Klasse von Problemen lösen sie, die vor ihrer Einführung nicht möglich waren?

A: Es ist eine Art Syntaxzucker wie das Überladen von Operatoren anstelle von Funktionen für benutzerdefinierte Add-, Subrtact- Operationen ... Aber es werden mehr Zeilen nicht benötigten Codes gespart, um 1-3 Zeilen umzubrechen von echter Logik zu einigen Klassen usw.! Einige Ingenieure denken, wenn die Anzahl der Zeilen kleiner ist, besteht eine geringere Wahrscheinlichkeit, dass Fehler darin auftreten (ich denke auch, dass dies der Fall ist).

Anwendungsbeispiel

auto x = [=](int arg1){printf("%i", arg1); };
void(*f)(int) = x;
f(1);
x(1);

Extras zu Lambdas, die nicht in Frage kommen. Ignorieren Sie diesen Abschnitt, wenn Sie kein Interesse haben.

1. Erfasste Werte. Was du einfangen kannst

1.1. Sie können in Lambdas auf eine Variable mit statischer Speicherdauer verweisen. Sie sind alle gefangen.

1.2. Sie können Lambda verwenden, um Werte "nach Wert" zu erfassen. In diesem Fall werden erfasste Variablen in das Funktionsobjekt (Closure) kopiert.

[captureVar1,captureVar2](int arg1){}

1.3. Sie können Referenz sein. & - bedeutet in diesem Zusammenhang Referenz, keine Zeiger.

   [&captureVar1,&captureVar2](int arg1){}

1.4. Es gibt die Notation, alle nicht statischen Variablen nach Wert oder Referenz zu erfassen

  [=](int arg1){} // capture all not-static vars by value

  [&](int arg1){} // capture all not-static vars by reference

1.5. Es gibt die Notation, alle nicht statischen Variablen nach Wert oder Referenz zu erfassen und smth anzugeben. Mehr. Beispiele: Erfassen Sie alle nicht statischen Variablen nach Wert, aber nach Referenz, erfassen Sie Parameter2

[=,&Param2](int arg1){} 

Erfassen Sie alle nicht statischen Variablen anhand der Referenz, aber anhand der Werterfassung Param2

[&,Param2](int arg1){} 

2. Rückgabetyp Abzug

2.1. Lambda-Rückgabetyp kann abgeleitet werden, wenn Lambda ein Ausdruck ist. Oder Sie können es explizit angeben.

[=](int arg1)->trailing_return_type{return trailing_return_type();}

Wenn Lambda mehr als einen Ausdruck hat, muss der Rückgabetyp über den nachfolgenden Rückgabetyp angegeben werden. Eine ähnliche Syntax kann auch auf Auto-Funktionen und Member-Funktionen angewendet werden

3. Erfasste Werte. Was Sie nicht erfassen können

3.1. Sie können nur lokale Variablen erfassen, keine Mitgliedsvariablen des Objekts.

4. Сonversions

4.1 !! Lambda ist kein Funktionszeiger und keine anonyme Funktion, aber capture-less Lambdas können implizit in einen Funktionszeiger konvertiert werden.

ps.

  1. Weitere Informationen zur Lambda-Grammatik finden Sie im Arbeitsentwurf für die Programmiersprache C++ # 337 vom 16.01.2012, 5.1.2. Lambda-Ausdrücke, S.88

  2. In C++ 14 wurde die zusätzliche Funktion "Init Capture" hinzugefügt. Es ermöglicht die willkürliche Deklaration von Closure-Datenelementen:

    auto toFloat = [](int value) { return float(value);};
    auto interpolate = [min = toFloat(0), max = toFloat(255)](int value)->float { return (value - min) / (max - min);};
    
38
bruziuz

Eine Lambda-Funktion ist eine anonyme Funktion, die Sie inline erstellen. Es kann Variablen erfassen, wie einige erklärt haben (z. B. http://www.stroustrup.com/C++11FAQ.html#lambda ), aber es gibt einige Einschränkungen. Wenn es zum Beispiel eine solche Callback-Schnittstelle gibt,

void apply(void (*f)(int)) {
    f(10);
    f(20);
    f(30);
}

sie können an Ort und Stelle eine Funktion schreiben, um sie wie die unten angegebene zu verwenden:

int col=0;
void output() {
    apply([](int data) {
        cout << data << ((++col % 10) ? ' ' : '\n');
    });
}

Aber das kannst du nicht machen:

void output(int n) {
    int col=0;
    apply([&col,n](int data) {
        cout << data << ((++col % 10) ? ' ' : '\n');
    });
}

wegen Einschränkungen im C++ 11-Standard. Wenn Sie Captures verwenden möchten, müssen Sie sich auf die Bibliothek und verlassen

#include <functional> 

(oder ein anderer STL-Bibliothek wie Algorithmus, um es indirekt zu erhalten) und dann mit std :: function zu arbeiten, anstatt normale Funktionen als Parameter wie folgt zu übergeben:

#include <functional>
void apply(std::function<void(int)> f) {
    f(10);
    f(20);
    f(30);
}
void output(int width) {
    int col;
    apply([width,&col](int data) {
        cout << data << ((++col % width) ? ' ' : '\n');
    });
}
15
Ted

Eine der besten Erklärungen für _lambda expression_ gibt der Autor von C++ Bjarne Stroustrup in seinem Buch _***The C++ Programming Language***_ Kapitel 11 (- ISBN-13: 978-0321563842 ):

What is a lambda expression?

Ein Lambda-Ausdruck , manchmal auch als Lambda -Funktion oder (genau genommen falsch, aber umgangssprachlich) als Lambda ist eine vereinfachte Notation zum Definieren und Verwenden eines anonymen Funktionsobjekts . Anstatt eine benannte Klasse mit einem operator () zu definieren, später ein Objekt aus dieser Klasse zu machen und es schließlich aufzurufen, können wir eine Kurzform verwenden.

When would I use one?

Dies ist besonders nützlich, wenn Sie eine Operation als Argument an einen Algorithmus übergeben möchten. Im Zusammenhang mit grafischen Benutzeroberflächen (und anderswo) werden solche Vorgänge häufig als Rückrufe bezeichnet.

What class of problem do they solve that wasn't possible prior to their introduction?

Hier denke ich, dass jede mit Lambda-Ausdruck durchgeführte Aktion ohne sie gelöst werden kann, aber mit viel mehr Code und viel größerer Komplexität. Lambda-Ausdruck Dies ist die Methode zur Optimierung und Attraktivierung Ihres Codes. So traurig von Stroustup:

effektive Möglichkeiten zur Optimierung

Some examples

über Lambda-Ausdruck

_void print_modulo(const vector<int>& v, ostream& os, int m) // output v[i] to os if v[i]%m==0
{
    for_each(begin(v),end(v),
        [&os,m](int x) { 
           if (x%m==0) os << x << '\n';
         });
}
_

oder über Funktion

_class Modulo_print {
         ostream& os; // members to hold the capture list int m;
     public:
         Modulo_print(ostream& s, int mm) :os(s), m(mm) {} 
         void operator()(int x) const
           { 
             if (x%m==0) os << x << '\n'; 
           }
};
_

oder auch

_void print_modulo(const vector<int>& v, ostream& os, int m) 
     // output v[i] to os if v[i]%m==0
{
    class Modulo_print {
        ostream& os; // members to hold the capture list
        int m; 
        public:
           Modulo_print (ostream& s, int mm) :os(s), m(mm) {}
           void operator()(int x) const
           { 
               if (x%m==0) os << x << '\n';
           }
     };
     for_each(begin(v),end(v),Modulo_print{os,m}); 
}
_

wenn du brauchst, kannst du _lambda expression_ wie folgt benennen:

_void print_modulo(const vector<int>& v, ostream& os, int m)
    // output v[i] to os if v[i]%m==0
{
      auto Modulo_print = [&os,m] (int x) { if (x%m==0) os << x << '\n'; };
      for_each(begin(v),end(v),Modulo_print);
 }
_

Oder nehmen Sie eine andere einfache Probe an

_void TestFunctions::simpleLambda() {
    bool sensitive = true;
    std::vector<int> v = std::vector<int>({1,33,3,4,5,6,7});

    sort(v.begin(),v.end(),
         [sensitive](int x, int y) {
             printf("\n%i\n",  x < y);
             return sensitive ? x < y : abs(x) < abs(y);
         });


    printf("sorted");
    for_each(v.begin(), v.end(),
             [](int x) {
                 printf("x - %i;", x);
             }
             );
}
_

wird als nächstes erzeugen

1

1

1

1

1

0 sortiertx - 1; x - 3; x - 4; x - 5; x - 6; x - 7; x - 33;

_[]_ - Dies ist die Erfassungsliste oder _lambda introducer_: Wenn lambdas keinen Zugriff auf ihre lokale Umgebung erfordern, können wir sie verwenden.

Zitat aus dem Buch:

Das erste Zeichen eines Lambda-Ausdrucks ist immer [. Ein Lambda-Einführer kann verschiedene Formen annehmen:

[] : eine leere Erfassungsliste. Dies impliziert, dass im Lambda-Körper keine lokalen Namen aus dem umgebenden Kontext verwendet werden können. Für solche Lambda-Ausdrücke werden Daten aus Argumenten oder nichtlokalen Variablen erhalten.

[&] : implizit durch Referenz erfassen. Alle lokalen Namen können verwendet werden. Auf alle lokalen Variablen wird per Referenz zugegriffen.

[=] : implizit nach Wert erfassen. Alle lokalen Namen können verwendet werden. Alle Namen beziehen sich auf Kopien der lokalen Variablen, die zum Zeitpunkt des Aufrufs des Lambda-Ausdrucks erstellt wurden.

[Erfassungsliste]: explizite Erfassung; Die Erfassungsliste ist die Liste der Namen lokaler Variablen, die nach Referenz oder nach Wert erfasst (d. h. im Objekt gespeichert) werden sollen. Variablen mit Namen, denen & vorangestellt ist, werden als Referenz erfasst. Andere Variablen werden nach Wert erfasst. Eine Erfassungsliste kann dies auch und Namen gefolgt von ... als Elemente enthalten.

[&, Erfassungsliste] : Erfasst implizit alle lokalen Variablen mit Namen, die nicht in der Liste aufgeführt sind. Die Erfassungsliste kann dies enthalten. Aufgeführte Namen dürfen nicht mit & beginnen. In der Erfassungsliste genannte Variablen werden nach Wert erfasst.

[=, capture-list] : Erfasst implizit alle lokalen Variablen mit Namen, die nicht in der Liste aufgeführt sind. Die Erfassungsliste kann dies nicht enthalten. Den aufgelisteten Namen muss & vorangestellt sein. In der Erfassungsliste genannte Variablen werden als Referenz erfasst.

Beachten Sie, dass ein lokaler Name mit vorangestelltem & immer als Referenz und ein lokaler Name ohne vorangestelltem & immer als Wert erfasst wird. Nur durch Referenzerfassung können Variablen in der aufrufenden Umgebung geändert werden.

Additional

_Lambda expression_ Format

enter image description here

Zusätzliche Referenzen:

11
gbk

Nun, eine praktische Anwendung, die ich herausgefunden habe, ist das Reduzieren des Kesselplattencodes. Zum Beispiel:

void process_z_vec(vector<int>& vec)
{
  auto print_2d = [](const vector<int>& board, int bsize)
  {
    for(int i = 0; i<bsize; i++)
    {
      for(int j=0; j<bsize; j++)
      {
        cout << board[bsize*i+j] << " ";
      }
      cout << "\n";
    }
  };
  // Do sth with the vec.
  print_2d(vec,x_size);
  // Do sth else with the vec.
  print_2d(vec,y_size);
  //... 
}

Ohne Lambda müssen Sie möglicherweise etwas für verschiedene bsize Fälle tun. Natürlich könnten Sie eine Funktion erstellen, aber was ist, wenn Sie die Verwendung im Rahmen der Soul-Benutzerfunktion einschränken möchten? Die Natur von Lambda erfüllt diese Anforderung, und ich verwende sie für diesen Fall.

2
Misgevolution

Die Lambdas in c ++ werden als "on the go available function" behandelt. ja es ist buchstäblich unterwegs, du definierst es; benutze es; und wenn der übergeordnete Funktionsumfang beendet ist, ist die Lambda-Funktion verschwunden.

c ++ führte es in c ++ 11 ein und jeder fing an, es wie an jedem möglichen Ort zu benutzen. Das Beispiel und was Lambda ist, finden Sie hier https://en.cppreference.com/w/cpp/language/lambda

Ich werde beschreiben, was es nicht gibt, aber für jeden C++ - Programmierer unbedingt zu wissen gibt

Lambda darf nicht überall verwendet werden und jede Funktion kann nicht durch Lambda ersetzt werden. Es ist auch nicht das schnellste im Vergleich zur normalen Funktion. weil es einige Gemeinkosten hat, die von Lambda behandelt werden müssen.

in einigen Fällen wird dies sicherlich dazu beitragen, die Anzahl der Leitungen zu verringern. Es kann grundsätzlich für den Codeabschnitt verwendet werden, der einmal oder mehrmals in derselben Funktion aufgerufen wird, und dieser Codeabschnitt wird an keiner anderen Stelle benötigt, damit Sie eine eigenständige Funktion für ihn erstellen können.

Nachfolgend finden Sie ein grundlegendes Beispiel für Lambda und die Vorgänge im Hintergrund.

Benutzercode:

int main()
{
  // Lambda & auto
  int member=10;
  auto endGame = [=](int a, int b){ return a+b+member;};

  endGame(4,5);

  return 0;

}

Wie Kompilieren es erweitert:

int main()
{
  int member = 10;

  class __lambda_6_18
  {
    int member;
    public: 
    inline /*constexpr */ int operator()(int a, int b) const
    {
      return a + b + member;
    }

    public: __lambda_6_18(int _member)
    : member{_member}
    {}

  };

  __lambda_6_18 endGame = __lambda_6_18{member};
  endGame.operator()(4, 5);

  return 0;
}

sie sehen also, welche zusätzlichen Kosten entstehen, wenn Sie es verwenden. Es ist also keine gute Idee, sie überall zu verwenden. es kann an Orten verwendet werden, an denen sie anwendbar sind.

1
Sachin Nale

Ein Problem, das dadurch gelöst wird: Code einfacher als Lambda für einen Aufruf im Konstruktor, der eine Ausgabeparameterfunktion zum Initialisieren eines const-Members verwendet

Sie können ein const-Mitglied Ihrer Klasse mit einem Aufruf einer Funktion initialisieren, die ihren Wert festlegt, indem Sie ihre Ausgabe als Ausgabeparameter zurückgeben.

1
sergiol