Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

wyrażenia lambda "[]()->typ {};"

Ostatnio zmodyfikowano 2017-01-06 22:53
Autor Wiadomość
Nazgul
Temat założony przez niniejszego użytkownika
wyrażenia lambda "[]()->typ {};"
» 2017-01-05 00:51:45
Kiedy są tworzone wyrażenia lambda?

C/C++
void foo() {
    auto lambda1 =[]()->void { return; };
   
    static auto lambda2 =[]()->void { return; };
   
    void( * lambda3 )() =[]()->void { return; };
}

Byłem przekonany, że są kompilowane jak każda inna funkcja - globalnie, tylko dostęp do nich jest jak po użyciu przedrostka static.
No właśnie straciłem pewność, gdy pomyślałem raz o dopisaniu "static" (jak przy lambda2 z powyższego przykładu).

Dlatego, żeby mieć pewność: Czy wyrażenia lambda tworzą się za każdym razem przy wejściu w funkcję? (tak jak zmienne.. z tego co wiem w assembly nie ma różnicy miedzy kodem a danymi)
Czy to działa tak, że określenie static dotyczy jedynie wskaźnika na funkcję, a sama funkcja sama w sobie jest statyczna? (zapis poglądowy):
C/C++
auto lambda1 =( static )[]()->void { return; };
static auto lambda =( static )[]()->void { return; };

Wiem, że pytanie zadane w dość pogmatwany sposób i z góry za to przepraszam, lepiej nie umiałem;P Będę wdzięczny za każdą pomoc;)
P-156009
mokrowski
» 2017-01-05 01:02:42
Lambdy to funktor czyli klasa z zaimplementowanym operatorem: operator(...) instancjonowana do _obiektu_funktora_ w momencie użycia. W nawiasach kwadratowych przekazujesz argumenty konstruktora, w nawiasach okrągłych argumenty do operator(...). Taki lukier składniowy :-)
Jeśli to funktor to obowiązują takie same zasady jak dla tworzenia instancji klas (funktor jest klasą). To oczywiście skrótowe wyjaśnienie a dość zwięzły opis znajdziesz tu: http://en.cppreference.com/w​/cpp/language/lambda

static to z kolei klasa pamięci. Wszelkie obiekty które posiadają static, są inicjowane jeszcze w "rozbiegówce" programu C++ (i C zresztą także). A jeśli lambda to funktor, to także jest wtedy inicjowana. Jeśli więc static lambda będzie "łapała" argumenty (nawiasy kwadratowe) przez referencję, referencja jeszcze wtedy (na etapie "rozbiegówki") będzie nieprawidłowa (jasne.. może być statyczna tylko na co Ci taka referencja?) a lambda powstanie (bo jest static) i przy 1 wywołaniu pięknie Ci się ... "wyłoży" (dokładniej UB). Stąd jeśli masz static lambdy, lepiej aby łapały argumenty przez kopię :-)

Najprościej jak umiałem bo nie chcę pisać elaboratu...

Tu masz przykład takiego wrednego kodu który albo zadziała albo nie jeśli odkomentujesz to co jest polecone w tagach XXX:
C/C++
#include <iostream>

using namespace std;

void trouble_function( int a ) {
    static bool running = false; // W trakcie 1 definiowania zapewnione false bo jest static
   
    int z = a + 1;
   
    static auto first_time_init_lambda =[ a ]() {
        cout << a << " first_time_init_lambda() " << endl;
    };
   
    first_time_init_lambda();
   
    // Zdefiniuje lambdę jeśli to nie pierwsze uruchomienie
    // XXX: Komentuj linię poniżej oraz...
    if( running > 0 ) {
        static auto first_time_error_lambda =[ & z ]() {
            cout << z << " first_time_error_lambda() " << endl;
        };
       
        first_time_error_lambda();
        // XXX: ... także tę poniżej..
    }
   
    running = true;
}

int main() {
    cout << "Start program" << endl;
    cout << "First run" << endl;
    trouble_function( 42 );
    cout << "Second run" << endl;
    trouble_function( 42 );
    cout << "End program" << endl;
}
P-156011
Monika90
» 2017-01-05 17:35:48
Kiedy są tworzone wyrażenia lambda?
Wyrażenie to coś co jest w tekście programu, czyli to Ty je tworzysz pisząc.

Wszelkie obiekty które posiadają static, są inicjowane jeszcze w "rozbiegówce" programu C++ (i C zresztą także).
Zmienne static w funkcjach są inicjalizowane kiedy sterowanie dojdzie po raz pierwszy do ich definicji.
P-156036
Nazgul
Temat założony przez niniejszego użytkownika
» 2017-01-06 22:53:53
Dziękuję;)
P-156139
« 1 »
  Strona 1 z 1