Wenn Sie Leistung wünschen, übergeben Sie den Wert, wenn Sie ihn speichern.
Angenommen, Sie haben eine Funktion namens "Führen Sie dies im UI-Thread aus".
std::future<void> run_in_ui_thread( std::function<void()> )
Das führt einen Code im "UI" -Thread aus und signalisiert dann, futurewann fertig. (Nützlich in UI-Frameworks, in denen sich der UI-Thread dort befindet, wo Sie mit UI-Elementen herumspielen sollen.)
Wir haben zwei Unterschriften, die wir in Betracht ziehen:
std::future<void> run_in_ui_thread( std::function<void()> ) // (A)
std::future<void> run_in_ui_thread( std::function<void()> const& ) // (B)
Nun werden wir diese wahrscheinlich wie folgt verwenden:
run_in_ui_thread( [=]{
// code goes here
} ).wait();
Dadurch wird ein anonymer Abschluss (ein Lambda) erstellt, ein std::functionOut daraus erstellt, an die run_in_ui_threadFunktion übergeben und gewartet, bis die Ausführung im Hauptthread abgeschlossen ist.
In Fall (A) wird das std::functiondirekt aus unserem Lambda konstruiert, das dann innerhalb des verwendet wird run_in_ui_thread. Das Lambda wird movein den std::functionZustand gebracht, so dass jeder bewegliche Zustand effizient in ihn hineingetragen wird.
Im zweiten Fall wird ein Temporär std::functionerstellt, das Lambda wird darin moveeingefügt, dann dieses Temporärstd::function als Referenz innerhalb des verwendet run_in_ui_thread.
So weit, so gut - die beiden arbeiten identisch. Außer das run_in_ui_threadwird eine Kopie seines Funktionsarguments erstellen, um es zur Ausführung an den UI-Thread zu senden! (Es wird zurückgegeben, bevor es damit fertig ist, daher kann es nicht einfach einen Verweis darauf verwenden.) Für Fall (A) legen wir einfach movedas std::functionin seine Langzeitlagerung. In Fall (B) sind wir gezwungen, das zu kopierenstd::function .
Dieser Laden macht die Wertübergabe optimaler. Wenn die Möglichkeit besteht, dass Sie eine Kopie von speichern std::function, übergeben Sie den Wert. Ansonsten ist jeder Weg ungefähr gleichwertig: Der einzige Nachteil des Nebenwerts besteht darin, dass Sie denselben sperrigen nehmen std::functionund eine Submethode nach der anderen verwenden. Ansonsten ist a moveso effizient wie a const&.
Nun gibt es einige andere Unterschiede zwischen den beiden, die meistens auftreten, wenn wir einen anhaltenden Zustand innerhalb der haben std::function.
Angenommen, das std::functionObjekt wird mit einem gespeichert operator() const, es enthält jedoch auch einige mutableDatenelemente, die geändert werden (wie unhöflich!).
In diesem std::function<> const&Fall werden die mutablegeänderten Datenelemente aus dem Funktionsaufruf weitergegeben. In diesem std::function<>Fall werden sie nicht.
Dies ist ein relativ seltsamer Eckfall.
Sie möchten std::functionwie jeder andere möglicherweise schwere, billig bewegliche Typ behandeln. Umzug ist billig, Kopieren kann teuer sein.
sizeof(std::function), dass es nicht mehr als ist2 * sizeof(size_t), was die kleinste Größe ist, die Sie jemals für eine konstante Referenz in Betracht ziehen würden.