Lebenszeit von Lambda-Funktionen



  • Hi,

    ich frage mich gerade, wie es mit der Lebenszeit von Lambda-Funktionen aussieht. Hier mal ein Beispiel:

    #include <iostream>
    #include <string>
    #include <vector>
    #include <functional>
    
    int main()
    {
      std::vector<std::function<void(std::string)>> v;
      {
        auto f = [] (std::string s) { std::cout << s; };
        v.push_back(f);
      }
      v.back()("Hallo!");
    }
    

    Bleibt der Pointer gültig? Es funktioniert bei mir zwar, aber das muss ja nichts bedeuten. Sehr schön wäre gleich eine passende Stelle im Standard, falls jemand da etwas findet.
    (Ich vermute mal es bleibt gültig, Funktionscode auf dem Stack würde irgendwie keinen Sinn machen, aber man weiß ja nie.)



  • Die Antwort würde mich auch interessieren. Ich bin kein Standard-Experte.

    N3242=11-0012 (5.1.2.2) schrieb:

    The type of the lambda-expression (which is also the type of the closure object) is a unique, unnamed non-union class type — called the closure type — whose properties are described below.

    Für mich liest sich das so, als wäre f eine Instanz einer Klasse und kein Funktionszeiger auf eine lokale Funktion.

    5.1.2.19 schrieb:

    The closure type associated with a lambda-expression has [...] an implicitly-declared copy constructor (12.8).

    Also kannst du f nach Belieben kopieren und weiterreichen. Die Funktion ist damit nicht an f gebunden. Was mit dem möglicherweise vorhandenen Capture passiert hab ich jetzt nicht nachgeschaut.



  • Also kannst du f nach Belieben kopieren und weiterreichen. Die Funktion ist damit nicht an f gebunden.

    Genau. Stellts Euch als Funktor vor.

    Was mit dem möglicherweise vorhandenen Capture passiert hab ich jetzt nicht nachgeschaut.

    Die werden kopiert - falls [&] werden die Referenzen kopiert, falls [=] werden sie direkt (die Values) kopiert.



  • cooky451 schrieb:

    Bleibt der Pointer gültig?

    Welcher Pointer, du hast in deinem ganzen Code keinen Pointer.
    Wieso machst du dir dann sorgen?



  • Ums kurz zu machen: Lambdas sind nichts als syntaktischer Zucker. Sie ermöglichen nichts, was mit C++03 nicht (sehr viel umständlicher) möglich gewesen wäre, und sie verhalten sich nicht anders als passend implementierte C++03-Funktoren. Simples Beispiel:

    void foo()
    {
      int i = 2;
      double d = 3.0;
    
    //auto myLambda = [&i, d](){return i+d;};
    
      struct Cpp0x_would_use_a_lambda
      {
        int& i_;   //capture by reference
        double d_; //capture by value
        Cpp0x_would_use_a_lambda(int& i, double const& d)
          : i_(i), d_(d) {}
    
        double operator(){ return i+d; }
    
      } myLambda(i,d);
    
      cout << myLambda() << '\n';
      ++i;
      d =* 4.0;
      cout << myLambda() << '\n';
    }
    

    Lambdas sind halt sehr viel schneller zu schreiben als die lokalen Funktorklassen.

    Was die std::function angeht: die wird sich eine lokale Kopie des Funktors halten und mit sich rumschleppen - also kein Grund zur Panik, solange evtl. gecapturete Referenzen nicht aus dem Scope laufen 😉



  • Alles klar. 👍



  • @pumuckl: kleine Korrektur noch: per Default ist die operator()-Funktion const-qualifiziert, was man mit dem mutable-Schlüsselwort dann aber explizit umgehen kann.


Log in to reply