Zum Beispiel habe ich folgenden Code:
auto z = [](int x) -> int {
if (x > 0) {
switch (x) {
case 2: return 5;
case 3: return 6;
default: return 1;
}
}
return 0;
};
Und später rufe ich das mehrmals an. In ASM-Code sehe ich externe Anrufe mit Lambda .... etwas ... Es wird nicht mehr einfach zu lesen und ich denke, es kann auch zu Leistung führen. Vielleicht gewinne ich bei der Metaprogrammierung, aber verliere ich bei der Fehlerbehebung und der Leistung? Sollte ich auf moderne Sprachfunktionen, Makros und andere Aspekte der Metaprogrammierung verzichten, um die Leistung zu verbessern und das Debuggen zu vereinfachen?
if
ist im Beispielcode völlig redundant, und während der Compiler wahrscheinlich feststellen wird, dass es keinen Grund gibt, eine schlechte Verzweigungsvorhersage zu versuchen.Antworten:
Nein , nicht, wenn Sie Ihren Code zum ersten Mal schreiben und keine echten, messbaren Leistungsprobleme haben. Für die meisten Aufgaben ist dies der Standardfall. Zu frühes Nachdenken über Optimierung wird als "vorzeitige Optimierung" bezeichnet, und es gibt gute Gründe, warum D. Knuth dies als "die Wurzel allen Übels" bezeichnet hat .
Ja , wenn Sie einen echten, nachweisbaren Leistungsengpass messen und dieses spezifische Lambda-Konstrukt als Grundursache identifizieren. In diesem Fall ist es möglicherweise eine gute Idee, sich an Joel Spolskys "Gesetz der undichten Abstraktionen" zu erinnern und darüber nachzudenken, was auf ASM-Ebene passieren könnte. Aber Vorsicht, Sie werden erstaunt sein, wie gering die Leistungssteigerung sein wird, wenn Sie ein Lambda-Konstrukt durch ein "nicht so modernes" Sprachkonstrukt ersetzen (zumindest, wenn Sie einen anständigen C ++ - Compiler verwenden).
quelle
Die Wahl zwischen Lambda und Funktorklasse ist ein Kompromiss.
Der Gewinn von Lambda ist größtenteils syntaktisch, indem die Menge an Boilerplate minimiert wird und konzeptionell relevanter Code innerhalb der Funktion, die ihn verwenden wird (sofort oder später), inline geschrieben werden kann.
In Bezug auf die Leistung ist dies nicht schlechter als eine Funktorklasse , die eine C ++ - Struktur oder -Klasse ist, die eine einzelne "Methode" enthält. Tatsächlich behandeln Compiler Lambda nicht anders als eine vom Compiler generierte Funktorklasse hinter den Kulissen.
In Ihrem Codebeispiel unterscheidet es sich in Bezug auf die Leistung nicht von einem Funktionsaufruf, da diese Funktionsklasse zufällig keinen Status hat (weil sie eine leere Erfassungsklausel enthält) und daher keine Zuordnung, keinen Konstruktor oder Zerstörung erfordert.
Das Debuggen von nicht-trivialem C ++ - Code mit einem Disassembler war schon immer eine schwierige Aufgabe. Dies gilt mit oder ohne Lambda. Dies wird durch die ausgeklügelte Codeoptimierung durch den C ++ - Compiler verursacht, die zu einer Neuordnung, Verschachtelung und Beseitigung von totem Code führte.
Der Name-Mangling-Aspekt ist etwas unangenehm und die Debugger-Unterstützung für Lambda steckt noch in den Kinderschuhen . Es kann nur gehofft werden, dass sich die Debugger-Unterstützung mit der Zeit verbessern wird.
Derzeit ist die beste Methode zum Debuggen von Lambda-Code die Verwendung eines Debuggers, der das Festlegen von Haltepunkten auf Quellcodeebene unterstützt, dh durch Angabe des Namens der Quelldatei und der Zeilennummer.
quelle
Um die Antwort von @DocBrown zu ergänzen, denken Sie daran, dass heutzutage CPUs billig, Arbeitskräfte jedoch teuer sind.
Bei den Gesamtkosten eines Programms ist Hardware im Vergleich zu den Wartungskosten, die bei weitem den teuersten Teil eines typischen Projekts ausmachen (sogar mehr als dessen Entwicklung), in der Regel unbedeutend.
Daher muss Ihr Code die Wartung vor allem optimieren , es sei denn, die Leistung ist kritisch (und selbst dann muss die Wartung berücksichtigt werden).
quelle