2016-08-08 9 views
0

ich einen Button-Klasse haben, die eine onClick std :: function typisierten Feld und "setClickListener" Methode haben setzt jede Lambda-Funktion auf diese std :: Funktionsfeld wie folgt:C++ 11 Lambda-Nutzung als Delegierter mit std :: function

#include <functional> 

class Button { 

public: 

void doSomething() { 
    if(onClick) { 
     onClick(); 
    } 
} 

typedef std::function<void()> OnClickListener; 
OnClickListener onClick; 

void setClickListener(OnClickListener onClickCallBack) { 
    onClick = onClickCallBack; 
} 

}; 

In meinem Anwendungscode, ich schaffe eine Lambda-Funktion und Einstellung onClick Funktion der Taste wie unten zu sehen:

#include "Button.h" 

void onAnEventOccured() { 
    button->setClickListener([this]()->void { 
     // Do something 
     memberFunction(); 
     anotherMemberFunction(); 
     // etc... 
    }); 

} 

void memberFunction() { 
    // Do some work... 
} 

void anotherMemberFunction() { 
    // Do some work... 
} 

Nun ist der kritische Abschnitt dass onAnEventOccured Methode viele Male während der Anwendung des Lebens genannt Zyklus und die Lambda-Funktion wird erneut und aga gesetzt im. Ich laufe auf Visual Studio 2015 und setzen Debug-Trace-Punkt auf den Dekonstruktor der Klasse std :: function und kann sehen, dass es tracepoint trifft, während setClickListener gesetzt wird. Ich denke, das ist der Dekonstruktor der Lambda-Funktion, der zerstört wurde, während der Geltungsbereich der onAnEventOccured-Funktion verlassen wurde und die Version dieses Lambdas wie erwartet in der Button-Instanz gespeichert wurde.

Bin ich richtig? Gibt es ein Speicherleck auf dieser Architektur?

+1

Ihre beiden Fragen scheint völlig orthogonal. Und soweit der Trace-Punkt auf Destruktor geht, ist es wahrscheinlich das temporäre 'std :: function'-Objekt, das beim Konvertieren Ihres anonymen lambda-Objekts in das std :: function-Objekt, nicht des Destruktors des anonymen Objekts aka lambda, erzeugt wird. – Arunmu

+0

Es gibt kein Speicherleck, die Provisorien sind zerstört. Ich kann Ihre anderen Fragen nicht beantworten, da Ihr zweites Code-Fragment ungültig ist, weil Sie versuchen, 'this' außerhalb einer Member-Funktion zu verwenden. Wenn ich verstehe, was Sie zu tun versuchen, hätten Sie eine 'std :: function ' abhängig von einem Objekt, das möglicherweise zerstört wird, vielleicht können Sie Ihr Funktionsobjekt vom Typ 'std :: function 'damit Sie den Button auch explizit übergeben können. – EdMaster

+0

Danke für Kommentare. @EdMaster, ich kenne deine Bedenken und ich garantiere, dass "dieser" Zeiger gültig ist, weil es mein aktueller Bildschirm in der Anwendung und Rendering aktiv ist. –

Antwort

0

Sie können nicht nennen:

button->setClickListener([this]()->void { 
     // Do something 
     memberFunction(); 
     anotherMemberFunction(); 
     // etc... 
    }); 

im Konstruktor oder während eines anderen Initialisierungsmethode, die Sie auf Ihrem Anwendungscode?

Auch Ihr Code könnte eine Rvalue-Referenz bekommen.

void setClickListener(OnClickListener&& callback); 
+0

Vielen Dank für Ihre Mühe, aber meine Zuhörer werden während des Lebenszyklus der Anwendung entsprechend gehandhabter Ereignisse geändert. –

Verwandte Themen