2016-08-22 3 views
4

Ich erstelle ein Rückrufsystem mit std::function und std::map s. Die Karte verwendet int s als Schlüssel und die Werte sind std::function. Ich binde Methoden in diese Funktionen. Ich frage mich, ob ich map.erase(i) anrufen, wird das die std :: -Funktion aus dem Speicher löschen, oder werde ich ein Speicherleck haben? HierEntfernen von std :: function Lambda-Wrapped-Methode von Std :: Karte

ist einige Beispiel-Code:

#include <iostream> 
#include <functional> 
#include <map> 

using namespace std; 

class TestClass{ 
    public: 
     TestClass(int _i, map<int, function<void()>>& test_map):i(_i){ 
      test_map[i]=[&](){this->lambda_test();}; 
     }; 
     void lambda_test(){cout << "output" << " " << i<< endl;}; 
    private: 
     int i; 
}; 

int main() { 
    map<int, function<void()>> test_map; 
    TestClass* test = new TestClass(1, test_map); 
    test_map[1](); 
    delete test; 
    test_map.erase(1); // <-- here 
    };     

Ist die letzte test_map.erase(1); die std::function aus dem Speicher entfernen?

+0

Das einzige, was in diesem Code zu beachten ist, ist zwischen 'delete test;' und 'test_map.erase (1);' wobei das Lambda auf einen ''th'-Zeiger verweist. In diesem Beispiel ist dies nicht schädlich, aber "wachsende" Anwendungen oder Multithread-Anwendungen könnten unbestimmtes Verhalten zeigen. Im Allgemeinen gibt es ein seltsames Lebenszeitproblem im Code, das durch das Speichern von TestClass in der Map anstelle von Lambda gelöst werden könnte. – stefaanv

Antwort

3

Das ist zwar kein guter Code, aber es gibt kein Speicherleck; Sie speichern die std::function s in der std::map nach Wert (anstatt mit Zeiger), daher wird std::map::erase den Destruktor std::function aufrufen.

Oder anders gesagt, Sie sind nicht new ing alle std::function, so dass Sie nicht brauchen delete keine std::function.

+0

Was macht es nicht guten Code? Sollte ich std :: function-Zeiger lieber als die tatsächlichen Objekte in der Karte speichern? –

+0

Aus Neugier, was speziell an diesem Code ist "nicht gut"? – sji

+0

@MaxTyler Warum 'neue TestClass'? Was macht "TestClass" überhaupt? Ich verstehe, dass dies ein Spielzeug-Beispiel ist, aber wenn Sie etwas wie dieses Muster in Ihrem tatsächlichen Code verwenden, dann vermute ich einen Designfehler. – Daniel

1

Es ist eine sehr gute Erklärung, was hier mit Lambda-Ausdrücke in Bezug auf die tatsächlichen Speicherzuordnung geht auf:

https://stackoverflow.com/a/12203426/1230538

Wie ich es verstehe, erzeugt die Lambda-Syntax einen r-Wert, kopiert (zusammen mit einem erfassten Zustand usw.) in die std :: -Funktion. Dies wird durch den Destruktor der std :: -Funktion gelöscht, der vom Destruktor der std :: map aufgerufen wird, wenn Sie löschen aufrufen (und/oder wenn die Karte den Gültigkeitsbereich verlässt).