Compiler-Optimierungen für Lambdas vs. einfache Funktionen
In seinem Buch „The C Standard Library (Second Edition)“ behauptet Nicolai Josuttis dass Lambdas vom Compiler besser optimiert werden können als einfache Funktionen. Dies mag kontraintuitiv erscheinen, da sowohl Lambdas als auch einfache Funktionen eingebunden werden können. Es gibt jedoch einen subtilen Unterschied zwischen den beiden, der bessere Optimierungen im Fall von Lambdas ermöglicht.
Der Unterschied: Funktionsobjekte vs. Funktionszeiger
Lambdas sind Funktionsobjekte, während einfache Funktionen im Wesentlichen Funktionszeiger sind. Bei der Übergabe eines Lambda an eine Funktionsvorlage wird eine neue Funktion speziell für dieses Objekt instanziiert. Dadurch kann der Compiler den Lambda-Aufruf einfach einbinden.
Im Gegensatz dazu führt die Übergabe einer einfachen Funktion an eine Funktionsvorlage dazu, dass ein Funktionszeiger übergeben wird. Compiler hatten in der Vergangenheit Probleme mit der Inlining-Aufrufe über Funktionszeiger. Obwohl sie theoretisch inline sein können, tritt dies nur auf, wenn die umgebende Funktion ebenfalls inline ist.
Ein Beispiel
Betrachten Sie die folgende Funktionsvorlage:
template <typename Iter, typename F> void map(Iter begin, Iter end, F f) { for (; begin != end; ++begin) *begin = f(*begin); }
Aufruf mit einem Lambda:
int a[] = { 1, 2, 3, 4 }; map(begin(a), end(a), [](int n) { return n * 2; });
Führt zu einer eindeutigen Instanziierung:
template <> void map<int*, _some_lambda_type>(int* begin, int* end, _some_lambda_type f) { for (; begin != end; ++begin) *begin = f.operator()(*begin); }
Der Compiler kann den Operator() des Lambda identifizieren und ihn trivial inline aufrufen.
Aber wenn es mit einem Funktionszeiger aufgerufen wird:
map(begin(a), end(a), &multiply_by_two);
Die Instanziierung wird zu:
template <> void map<int*, int (*)(int)>(int* begin, int* end, int (*f)(int)) { for (; begin != end; ++begin) *begin = f(*begin); }
Hier referenziert f bei jedem Aufruf von Map unterschiedliche Funktionen und verhindert so das Compiler vor Inlining-Aufrufen schützen, es sei denn, Map selbst ist inline.
Fazit
Der einzigartige Typ von Lambdas als Funktionsobjekte ermöglicht es Compilern, spezifische Funktionsinstanziierungen zu erstellen und ihre Aufrufe nahtlos einzubinden. Diese verbesserte Optimierungsfähigkeit unterscheidet Lambdas von einfachen Funktionen und macht sie zu einer bevorzugten Wahl für die Verbesserung der Codeleistung und -effizienz.
Das obige ist der detaillierte Inhalt vonKönnen Lambdas durch Compiler besser optimiert werden als einfache Funktionen?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!